Verilog 刷题笔记(04)
29.Build an AND gate using both an assign statement and a combinational always block.
// synthesis verilog_input_version verilog_2001 module top_module( input a, input b, output wire out_assign, output reg out_alwaysblock ); //assign语句 和 always块 是等效的 assign out_assign = a&b; always@(*) out_alwaysblock = a&b; endmodule
30. 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 ); //1.连续赋值 assign语句 assign out_assign = a^b ; //a异或b //2.阻塞赋值 always块 always@(*) out_always_comb = a^b; //a异或b //3.非阻塞赋值 always块 + 边沿触发 always@(posedge clk) out_always_ff <= a^b; //a异或b endmodule
输出图像:
31. 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.
// synthesis verilog_input_version verilog_2001 module top_module( input a, input b, input sel_b1, input sel_b2, output wire out_assign, output reg out_always ); //assign版 多路复用 assign out_assign = (sel_b1&sel_b2)?b:a; //always版 多路复用 always@(*) if(sel_b1&sel_b2)begin out_always = b; end else begin out_always = a; end endmodule
32. 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.
修改前:
module top_module ( input cpu_overheated, output reg shut_off_computer, input arrived, input gas_tank_empty, output reg keep_driving ); always @(*) begin shut_off_computer=cpu_overheated; end always @(*) begin keep_driving=(~arrived)&(~gas_tank_empty); end endmodule
修改后:
// synthesis verilog_input_version verilog_2001 //注:必须写全if else,否则会出现latch,报错 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; else shut_off_computer = 0; end always @(*) begin if ((~arrived)&(~gas_tank_empty)) keep_driving = 1; else keep_driving = 0; end endmodule
33.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.
// synthesis verilog_input_version verilog_2001 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; 3'b110: out<=4'b0000; 3'b111: out<=4'b0000; endcase end endmodule
34.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.
//这个当时没做出来,看了别人做的
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
//an easier way
always @(*) begin casez (in[3:0]) 4'bzzz1: out = 0; // in[3:1] can be anything 4'bzz1z: out = 1; 4'bz1zz: out = 2; 4'b1zzz: out = 3; default: out = 0; endcase end
35. Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first bit in the vector that is 1. Report zero if the input vector has no bits that are high. For example, the input 8'b10010000 should output 3'd4, because bit[4] is first bit that is high.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 bothx
andz
as don't-care. I don't see much purpose to using it overcasez
. -
The digit
?
is a synonym forz
. so2'bz0
is the same as2'b?0
// synthesis verilog_input_version verilog_2001 module top_module ( input [7:0] in, output reg [2:0] pos ); always@(*)begin casez(in) 8'bzzzzzzz1: pos = 0; 8'bzzzzzz1z: pos = 1; 8'bzzzzz1zz: pos = 2; 8'bzzzz1zzz: pos = 3; 8'bzzz1zzzz: pos = 4; 8'bzz1zzzzz: pos = 5; 8'bz1zzzzzz: pos = 6; 8'b1zzzzzzz: pos = 7; default:pos = 0; endcase end endmodule
36.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 |
Your circuit has one 16-bit input, and four outputs. Build this circuit that recognizes these four scancodes and asserts the correct output.To avoid creating latches, all outputs must be assigned a value in all possible conditions . Simply having a default case is not enough. You must assign a value to all four outputs in all four cases and the default case. This can involve a lot of unnecessary typing. One easy way around this is to assign a "default value" to the outputs before the case statement:
always @(*) begin up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0; case (scancode) ... // Set to 1 as necessary. endcase end
// synthesis verilog_input_version verilog_2001 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; case (scancode) // Set to 1 as necessary. //将上述的键盘的ASCII码和up、down、left、right进行链接 16'he06b:left = 1'b1; 16'he072:down = 1'b1; 16'he074:right = 1'b1; 16'he075:up = 1'b1; default: ; endcase end endmodule
37.Given four unsigned numbers, find the minimum. Unsigned numbers can be compared with standard comparison operators (a < b). Use the conditional operator to make two-way min circuits, then compose a few of them to create a 4-way min circuit. You'll probably want some wire vectors for the intermediate results. Expected solution length: Around 5 lines.
module top_module ( input [7:0] a, b, c, d, output [7:0] min); // assign intermediate_result1 = compare? true: false; //三目运算符 wire [7:0] minab,mincd; assign minab=(a>b)?b:a; assign mincd=(c>d)?d:c; assign min=(minab>mincd)?mincd:minab; endmodule
38. Parity checking is often used as a simple method of detecting errors when transmitting data through an imperfect channel. Create a circuit that will compute a parity bit for a 8-bit byte (which will add a 9th bit to the byte). We will use "even" parity, where the parity bit is just the XOR of all 8 data bits. Expected solution length: Around 1 line.
//Reduction operators
module top_module ( input [7:0] in, output parity); //奇偶校验,直接异或 assign parity = ^in[7:0]; endmodule
39. Build a combinational circuit with 100 inputs, in[99:0]. There are 3 outputs:
- out_and: output of a 100-input AND gate.
- out_or: output of a 100-input OR gate.
- out_xor: output of a 100-input XOR gate.
module top_module( input [99:0] in, output out_and, output out_or, output out_xor ); //在 [99:0] 中构建一个具有 100 个输入的组合电路。 assign out_and = &in[99:0]; //与 assign out_or = |in[99:0]; //或 assign out_xor = ^in[99:0]; //异或 endmodule
40.Given a 100-bit input vector [99:0], reverse its bit ordering.
module top_module( input [99:0] in, output [99:0] out ); //给定一个 100 位输入向量 [99:0],反转其位顺序。 always@(*) begin for(integer i = 0; i < 100;i = i+1) out[i] = in[99-i]; end endmodule