HDLbits
除工程文件使用vivado外,平时一直是使用 VScode 结合 iverilog 和 GTKwave 来练习,轻量省事。 在此记录下HDLbits网站练习,后边也放些别的练习。
//以下正文//
problem 14
Problem description
Gates4
out_and: output of a 4-input AND gate.
out_or: output of a 4-input OR gate.
out_xor: output of a 4-input XOR gate.
Solution
module top_module (
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = & in;
assign out_or = | in;
assign out_xor = ^ in;
endmodule
- 逐位逻辑运算符:对于 N 比特输入向量之间的逻辑比较,会在 N 比特上逐位进行,并产生一个 N 比特长的运算结果。
- 逻辑运算符:任何类型的输入都会被视作布尔值,将布尔值进行逻辑比较后,输出一个 1 比特的结果。
problem 15
Problem description
A Bit of Practice
5-bit input vectors: a, b, c, d, e.
8-bit output vectors: w, x, y, and z.
Solution
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
assign w = { a, b[4:2] };
assign x = { b[1:0], c, d[4] };
assign y = { d[3:0], e[4:1] };
assign z = { e[0], f, 2'b11 };
endmodule
- 连接操作符的基本语法使用 { } 将较小的向量括起来,每个 { } 内的向量使用逗号作为间隔。
- 连接运算符中的向量务必需要标注位宽。
- 这里是在赋值语句右侧使用位连接符,在左侧使用位连接符的场景也很常见,比如在全加器中使用一句 assign 语句实现结果和进位的赋值。
problem 16
Solution
module top_module(
input [7:0] in,
output reg [7:0] out
);
integer i;
always @(*) begin
for (i=0; i<8; i=i+1) begin
out[i] = in[8-i-1];
end
end
endmodule
problem 17
Solution
module top_module (
input [7:0] in,
output [31:0] out );//
// assign out = { replicate-sign-bit , the-input };
assign out = {{24{in[7]}}, in};
endmodule
problem 18
Solution
module top_module (
input a, b, c, d, e,
output [24:0] out );//
assign out = ~{ {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} } ^ {5{a, b, c, d, e}};
endmodule
//过于基础,不予记录//
problem 23
Problem description
Solution
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] q1, q2, q3;
my_dff8 dff_1 (clk, d, q1);
my_dff8 dff_2 (clk, q1, q2);
my_dff8 dff_3 (clk, q2, q3);
always @(*) begin
case (sel)
0: q = d;
1: q = q1;
2: q = q2;
3: q = q3;
endcase
end
endmodule
problem 29
Solution
// 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 @(*) begin
out_alwaysblock = a & b;
end
endmodule
problem 30
Solution
// 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 @(*) begin
out_always_comb = a ^ b;
end
always @(posedge clk) begin
out_always_ff <= a ^ b;
end
endmodule
problem 31
Solution
// 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 out_assign = (sel_b1 & sel_b2) ? b : a;
always @(sel_b1 or sel_b2) begin
if (sel_b1 & sel_b2) begin
out_always = b;
end else begin
out_always = a;
end
end
endmodule
problem 33
Solution
// 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;
default: out = 0;
endcase
end
endmodule
problem 36
Solution
// 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
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
problem 37
Solution
module top_module (
input [7:0] a, b, c, d,
output [7:0] min
);//
wire [7:0] intermediate_result1;
wire [7:0] intermediate_result2;
// assign intermediate_result1 = compare? true: false;
assign intermediate_result1 = a<b ? a:b;
assign intermediate_result2 = c<d ? c:d;
assign min = intermediate_result1<intermediate_result2 ? intermediate_result1:intermediate_result2;
endmodule
problem 40
Solution
module top_module(
input [99:0] in,
output reg [99:0] out
);
integer i;
always @(*) begin
for (i = 0; i<100; i = i+1) begin
out[i] = in[99-i];
end
end
endmodule
problem 41
Solution
module top_module(
input [254:0] in,
output [7:0] out
);
reg [7:0] cnt;
integer i;
always @(*) begin
cnt = 0;
for (i = 0; i < 255; i = i+1) begin
if (in[i] == 1) begin
cnt = cnt + 1'b1;
end else begin
cnt = cnt;
end
end
end
assign out = cnt;
endmodule
problem 42
Solution
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum
);
reg [99:0] cout_reg;
reg [99:0] sum_reg;
integer i;
always @(*) begin
cout_reg = 0;
sum_reg = 0;
{cout_reg[0], sum_reg[0]} = a[0] + b[0] + cin;
for (i = 1; i < 100; i = i+1) begin
{cout_reg[i], sum_reg[i]} = a[i] + b[i] + cout_reg[i-1];
end
end
assign cout = cout_reg;
assign sum = sum_reg;
endmodule
Other exercises
test 1
/*
//给定8个数,以及若干二输入比较器。
//要求在单周期内实现8个数的排序,
//并使用最好的比较器个数。
*/
module sort8 #(
parameter DW = 8
)(
input [DW-1:0] i_d0,
input [DW-1:0] i_d1,
input [DW-1:0] i_d2,
input [DW-1:0] i_d3,
input [DW-1:0] i_d4,
input [DW-1:0] i_d5,
input [DW-1:0] i_d6,
input [DW-1:0] i_d7,
output reg [DW-1:0] o_d0,
output reg [DW-1:0] o_d1,
output reg [DW-1:0] o_d2,
output reg [DW-1:0] o_d3,
output reg [DW-1:0] o_d4,
output reg [DW-1:0] o_d5,
output reg [DW-1:0] o_d6,
output reg [DW-1:0] o_d7
);
function [DW*2-1:0] max;
input [DW-1:0] data0;
input [DW-1:0] data1;
begin
max = data0 <= data1 ? {data1, data0} : {data0, data1};
end
endfunction
function [DW*4-1:0] max_4;
input [DW-1:0] d0;
input [DW-1:0] d1;
input [DW-1:0] d2;
input [DW-1:0] d3;
reg [DW-1:0] r0;
reg [DW-1:0] r1;
reg [DW-1:0] r2;
reg [DW-1:0] r3;
reg [DW-1:0] r4;
reg [DW-1:0] r5;
reg [DW-1:0] r6;
reg [DW-1:0] r7;
reg [DW-1:0] r8;
reg [DW-1:0] r9;
begin
{r0,r1} = max(d0,d1);
{r2,r3} = max(d2,d3);
{r4,r5} = max(r0,r2);
{r6,r7} = max(r1,r3);
{r8,r9} = max(r6,r5);
max_4 = {r4, r8, r9, r7};
end
endfunction
// reg [DW*4-1:0] max_4_r;
// always @(*) begin
// max_4_r = max_4(i_d0, i_d1, i_d2, i_d3);
// end
// assign o_d0 = max_4_r[ 7: 0];
// assign o_d1 = max_4_r[15: 8];
// assign o_d2 = max_4_r[23:16];
// assign o_d3 = max_4_r[31:24];
//8输入比较
reg [DW-1:0] m0, m1, m2, m3, m4, m5, m6, m7, m8, m9;
reg [DW-1:0] m10, m11, m12, m13, m14, m15, m16, m17, m18, m19;
always @(*) begin
{m0, m1, m2, m3} = max_4 (i_d0, i_d1, i_d2, i_d3);
{m4, m5, m6, m7} = max_4 (i_d4, i_d5, i_d6, i_d7);
{m8, m9, m10, m11} = max_4 (m0, m1, m4, m5);
{m12, m13, m14, m15} = max_4 (m2, m3, m6, m7);
{m16, m17, m18, m19} = max_4 (m10, m11, m12, m13);
o_d0 = m15;
o_d1 = m14;
o_d2 = m19;
o_d3 = m18;
o_d4 = m17;
o_d5 = m16;
o_d6 = m9;
o_d7 = m8;
end
endmodule
module sort8_tst();
reg [8-1:0] i_d0 ;
reg [8-1:0] i_d1 ;
reg [8-1:0] i_d2 ;
reg [8-1:0] i_d3 ;
reg [8-1:0] i_d4 ;
reg [8-1:0] i_d5 ;
reg [8-1:0] i_d6 ;
reg [8-1:0] i_d7 ;
wire [8-1:0]o_d0 ;
wire [8-1:0]o_d1 ;
wire [8-1:0]o_d2 ;
wire [8-1:0]o_d3 ;
wire [8-1:0]o_d4 ;
wire [8-1:0]o_d5 ;
wire [8-1:0]o_d6 ;
wire [8-1:0]o_d7 ;
sort8 U_sort8(
.i_d0(i_d0),
.i_d1(i_d1),
.i_d2(i_d2),
.i_d3(i_d3),
.i_d4(i_d4),
.i_d5(i_d5),
.i_d6(i_d6),
.i_d7(i_d7),
.o_d0(o_d0),
.o_d1(o_d1),
.o_d2(o_d2),
.o_d3(o_d3),
.o_d4(o_d4),
.o_d5(o_d5),
.o_d6(o_d6),
.o_d7(o_d7)
);
initial
begin
i_d0=8'd23;
i_d1=8'd87;
i_d2=8'd3;
i_d3=8'd76;
i_d4=8'd1;
i_d5=8'd2;
i_d6=8'd3;
i_d7=8'd4;
end
endmodule
test 2
module uart_tx(
//global clock
input clk,
input rst_n,
//uart interface
output reg uart_tx,
//user interface
input [31:0] pinlv,
input pinlv_value
);
parameter BPS_9600 = 5208;
//count for bps_clk
reg [14:0] cnt_bps_clk;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_bps_clk <= 1'b0;
end else if (pinlv_value == 0) begin
cnt_bps_clk <= 1'b0;
end else if (cnt_bps_clk == BPS_9600 - 1) begin
cnt_bps_clk <= cnt_bps_clk + 1'b1;
end
end
reg [31:0] cnt_bps_stop;
wire stop_done;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_bps_stop <= 0;
end else if (state == STOP) begin
cnt_bps_stop <= 0;
end else if (cnt_bps_stop > 50_000_00) begin
cnt_bps_stop <= 0;
end else
cnt_bps_stop <= cnt_bps_stop + 1'b1;
end
assign stop_done = (cnt_bps_stop == 49_000_00) ? 1 : 0;
//clk for bps
reg bps_clk;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
bps_clk <= 1'b0;
end else if (cnt_bps_clk == 1) begin
bps_clk <= 1'b1;
end else
bps_clk <= 1'b0;
end
//cnt for bps
reg [14:0] bps_cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
bps_cnt <= 1'b0;
end else if (bps_cnt == 10) begin
bps_cnt <= 0;
end else if (bps_clk) begin
bps_cnt <= bps_cnt + 1'b1;
end else
bps_cnt <= bps_cnt;
end
//tx state
localparam IDLE = 4'd0;
localparam TX_1 = 4'd1;
localparam TX_2 = 4'd2;
localparam TX_3 = 4'd3;
localparam TX_4 = 4'd4;
localparam STOP = 4'd5;
localparam STOP_1 = 4'd6;
//cnt state
reg [3:0] state;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
state <= IDLE;
else if (state == STOP_1 && stop_done)
state <= IDLE;
else if (bps_cnt == 10 && (state != STOP_1))
state <= state + 1'b1;
end
//state
always @(posedge clk) begin
if (bps_clk) begin
case (state)
IDLE : //'t' l -- h
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= 0; //data
4'd2 : uart_tx <= 0;
4'd3 : uart_tx <= 1;
4'd4 : uart_tx <= 0;
4'd5 : uart_tx <= 1;
4'd6 : uart_tx <= 1;
4'd7 : uart_tx <= 1;
4'd8 : uart_tx <= 0;
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
TX_1 : //tx_1byte
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= pinlv[24]; //data
4'd2 : uart_tx <= pinlv[25];
4'd3 : uart_tx <= pinlv[26];
4'd4 : uart_tx <= pinlv[27];
4'd5 : uart_tx <= pinlv[28];
4'd6 : uart_tx <= pinlv[29];
4'd7 : uart_tx <= pinlv[30];
4'd8 : uart_tx <= pinlv[31];
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
TX_2 : //tx_1byte
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= pinlv[16]; //data
4'd2 : uart_tx <= pinlv[17];
4'd3 : uart_tx <= pinlv[18];
4'd4 : uart_tx <= pinlv[19];
4'd5 : uart_tx <= pinlv[20];
4'd6 : uart_tx <= pinlv[21];
4'd7 : uart_tx <= pinlv[22];
4'd8 : uart_tx <= pinlv[23];
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
TX_3 :
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= pinlv[ 8]; //data
4'd2 : uart_tx <= pinlv[ 9];
4'd3 : uart_tx <= pinlv[10];
4'd4 : uart_tx <= pinlv[11];
4'd5 : uart_tx <= pinlv[12];
4'd6 : uart_tx <= pinlv[13];
4'd7 : uart_tx <= pinlv[14];
4'd8 : uart_tx <= pinlv[15];
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
TX_4 :
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= pinlv[0]; //data
4'd2 : uart_tx <= pinlv[1];
4'd3 : uart_tx <= pinlv[2];
4'd4 : uart_tx <= pinlv[3];
4'd5 : uart_tx <= pinlv[4];
4'd6 : uart_tx <= pinlv[5];
4'd7 : uart_tx <= pinlv[6];
4'd8 : uart_tx <= pinlv[7];
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
STOP :
begin
case (bps_cnt)
4'd0 : uart_tx <= 0; //begin
4'd1 : uart_tx <= pinlv[0]; //data
4'd2 : uart_tx <= pinlv[0];
4'd3 : uart_tx <= pinlv[0];
4'd4 : uart_tx <= pinlv[1];
4'd5 : uart_tx <= pinlv[1];
4'd6 : uart_tx <= pinlv[1];
4'd7 : uart_tx <= pinlv[1];
4'd8 : uart_tx <= pinlv[0];
4'd9 : uart_tx <= 1; //stop
default : uart_tx <= 1;
endcase
end
STOP_1 :
begin
uart_tx <= 1;
end
default : uart_tx <= 1;
endcase
end
else
uart_tx <= uart_tx;
end
endmodule
problem
Solution