前言
这是我第二次刷HDLBits的题,第一次是刚接触FPGA时,为了快速入门Verilog,第一次刷题跟着B站视频刷的,但是现在发现没有很大的用处,个人感觉还是有一点Verilog基础后,再来刷HDLBits会好一点,虽然很多人说这上面的题都很简单,但是还是值得刷一遍,里面几乎涵盖了Verilog的所有常用语法,并且还可以尝试用不同方法解同一道题。
代码
以下是我写的每道题的代码和思路
Procedure
注意:
- case、if-else语句要避免产生锁存器
// 使用always(*)组合逻辑
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b ;
always @(*) begin
out_alwaysblock = a & b;
end
endmodule
// 寄存器、always(clk)时序逻辑、异或
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 @(*) begin
out_always_comb = a ^ b;
end
always @(posedge clk) begin
out_always_ff <= a ^ b ;
end
endmodule
// 条件判断
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==1'b1)& (sel_b2==1'b1))?b:a;
always @(*) begin
if((sel_b1==1'b1)& (sel_b2==1'b1))
out_always = b;
else
out_always = a;
end
endmodule
// ======================= 4 =========================
// 如何避免产生锁存器:if-else写完
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)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
// case语句,注意位宽
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'd0: out = data0;
3'd1: out = data1;
3'd2: out = data2;
3'd3: out = data3;
3'd4: out = data4;
3'd5: out = data5;
default: out = 0;
endcase
end
endmodule
// 不要忘记写default
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*) begin
case(1)
in[0]: pos = 2'd0;
in[1]: pos = 2'd1;
in[2]: pos = 2'd2;
in[3]: pos = 2'd3;
default:pos = 2'd0;
endcase
end
endmodule
// casez
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez(in)
8'bzzzzzzz1:pos = 3'd0;
8'bzzzzzz1z:pos = 3'd1;
8'bzzzzz1zz:pos = 3'd2;
8'bzzzz1zzz:pos = 3'd3;
8'bzzz1zzzz:pos = 3'd4;
8'bzz1zzzzz:pos = 3'd5;
8'bz1zzzzzz:pos = 3'd6;
8'b1zzzzzzz:pos = 3'd7;
default:pos = 3'd0;
endcase
end
endmodule
// 为了避免产生锁存器,在使用case语句前,先给输出赋初值,这样就不用在case语句中使用default
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @(*) begin
left = 1'b0;
down = 1'b0;
right = 1'b0;
up = 1'b0;
case(scancode)
16'he06b: left = 1'b1;
16'he072: down = 1'b1;
16'he074: right = 1'b1;
16'he075: up = 1'b1;
endcase
end
endmodule