https://hdlbits.01xz.net/wiki/Build a Circuit from Simulation Waveform、testbench答案
1.sim
module top_module (
input a,
input b,
output q );//
assign q = a & b; // Fix me
endmodule
2.circuit2
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = ((~a) & (~b) & (~c) & (~d)) | ((~a) & (~b) & (c) & (d)) | ((~a) & (b) & (~c) & (d)) |
((~a) & (b) & (c) & (~d)) | ((a) & (~b) & (~c) & (d)) | ((a) & (~b) & (c) & (~d))
| ((a) & (b) & (~c) & (~d)) | ((a) & (b) & (c) & (d)); // Fix me
endmodule
一看这有一半是1我就怀疑不能化简的了。。。果然果然。
3.circuit3
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = ~(((~c) & (~d)) | ((~a) & (~b))); // Fix me
endmodule
这里q等于1有九个显然是可以化简的。
4.Circuit4
module top_module (
input a,
input b,
input c,
input d,
output q );//
assign q = ~((~b) & (~c)); // Fix me
endmodule
等于零的只有四个量,显然应该从此处下手
5.Circuit5
module top_module (
input [3:0] a,
input [3:0] b,
input [3:0] c,
input [3:0] d,
input [3:0] e,
output [3:0] q );
always@(*)begin
case(c)
4'd0: q = b;
4'd1: q = e;
4'd2: q = a;
4'd3: q = d;
default: q = 4'hf;
endcase
end
endmodule
从波形图可以看出来应该是一个四选一的MUX同时有默认输出4'b1111。组合电路必须有默认输出,否则就构成锁存器了。
6.Circuit6
module top_module (
input [2:0] a,
output [15:0] q );
always@(*)begin
case(a)
3'd0: q = 16'h1232;
3'd1: q = 16'haee0;
3'd2: q = 16'h27d4;
3'd3: q = 16'h5a0e;
3'd4: q = 16'h2066;
3'd5: q = 16'h64ce;
3'd6: q = 16'hc526;
3'd7: q = 16'h2f19;
default: q = 16'h0;
endcase
end
endmodule
这理应是一个八选一MUX,默认输出是我自己加的,但是建议还是要有,这毕竟是组合电路。
7.Circuit7
module top_module (
input clk,
input a,
output q );
always@(posedge clk)begin
if(~a)
q <= 1'b1;
else
q <= 1'b0;
end
endmodule
一个时钟控制的同步输出的反相器。
8.Circuit8
module top_module (
input clock,
input a,
output p,
output q );
reg p0;
reg p1;
always@(*)begin
if(clock)
p1 = a;
else
p1 = 1'b0;
end
always@(negedge clock)begin
q <= a;
p0 <= a;
end
assign p = (clock)? p1 : p0;
endmodule
首先这里q的逻辑简单,就是下降沿时把a赋值进来,p则是clock高电平同步a,下降沿时保持此时的a(或者说是保持上一个时刻的p),所以这里p有组合的部分也有时序的部分,因而必须把两部分分开最后用一个MUX接上再输出。
9.Circuit
module top_module (
input clk,
input a,
output [3:0] q );
always@(posedge clk)begin
if(a)
q <= 4'd4;
else if(q==4'd6)
q <= 4'd0;
else
q <= q + 4'd1;
end
endmodule
这个的逻辑也很清晰,是一个若a为高电平则同步置位为4,若a为低电平则计数,计数为7进制即到7就置零。
10.Circuit10
module top_module (
input clk,
input a,
input b,
output q,
output state );
reg next_state;
always@(*)begin
case(state)
1'b0: next_state = a & b;
1'b1: next_state = ~((~a) & (~b));
default: next_state = 1'b0;
endcase
end
always@(posedge clk)
state <= next_state;
assign q = (state)? ~(a^b) : (a^b); //异步输出
endmodule
观察波形就可以知道这里必须写异步输出。
以下是tb部分,只有五个所以写一起了
1.Clock
`timescale 1ps/1ps
module top_module ( );
reg clock;
initial
begin
clock = 0;
forever
#5 clock = ~clock;
end
dut dut_1(clock);
endmodule
在我的博客Verilog描述方法与层次的高级编程语句部分和Verilog 语言基础的编译指令部分中,已经写到了如何生成一个时钟。
读者如有兴趣可以去看一看。
2.tb1
module top_module ( output reg A, output reg B );//
// generate input patterns here
initial begin
A = 1'b0;
B = 1'b0;
#10 A = 1'b1;
#5 B = 1'b1;
#5 A = 1'b0;
#20 B = 1'b0;
end
/*fork
A <= 1'b0;
B <= 1'b0;
#10 A <= 1'b1;
#15 B <= 1'b1;
#20 A <= 1'b0;
#40 B <= 1'b0;
这是非阻塞的写法
join */
endmodule
这里我把顺序和并发的写法都写了出来,顺序的延时的计数的个数是针对上一个延时的时点,而并发延时则是针对整个测试的起点。
如有兴趣,读者可以看一看我的博客Verilog描述方法与层次中的语句组部分, 举例具体说明了两者的区别。
3.and Gate
module top_module();
reg[1:0] in;
reg out;
reg out1;
initial begin
#0 in = 2'b00;
#0 out = 1'b0;
#10 in = 2'b01;
#10 in = 2'b10;
#10 in = 2'b11;
#0 out = 1'b1;
end
andgate andgate1(in, out1);
endmodule
这里实际上就说明了一个tb是如何运行的,可以自己在写测试波形的时候同时写出应该得到的结果的波形,最后就将实例化结果的波形与预期波形作比较即可。
4.tb2
module top_module();
reg clk;
reg in;
reg[2:0] s;
reg out;
initial fork
#0 clk = 1'b0;
#0 s = 3'd2;
#0 in = 1'b0;
#10 s = 3'd6;
#20 s = 3'd2;
#20 in = 1'b1;
#30 s = 3'd7;
#30 in = 1'b0;
#40 s = 3'd0;
#40 in = 1'b1;
#70 in = 1'b0;
forever #5 clk = ~clk;
join
q7 q7_1(clk, in, s, out);
endmodule
实际写tb时就会发现,如果这里用顺序语句组begin...end就没法在initial块中全写出来,用并发语句组fork...join则可以避免这个问题了。主要是forever语句生成时钟带来的问题。使用并发语句组就可以避免了。
5.tb/dff
module top_module ();
reg clk;
reg reset;
reg t;
reg q;
initial fork
#0 clk = 1'b0;
#0 reset = 1'b1;
#0 t = 1'b0;
#10 reset = 1'b0;
#10 t = 1'b1;
forever #5 clk = ~clk;
join
tff tff_1(clk, reset, t, q);
endmodule
这是最后一题了,没什么难度,没有什么特别要注意的。
习题链接
如果有错误或者有别的想法,欢迎批评和讨论。
写在最后
到这里HDLbits所有的题目我就都完成了。
刚开始时我也就是个初学者,一点也不会,前前后后两周一边看书,看完一遍后再开始做题,边做又边整理书本上的内容,在状态机那里前前后后被折磨了四五天T.T真的挺痛苦的,但是我想这也是学习的必经之路,我的正确率也不算高,因为还保留着写软件代码时那种让ide来帮忙找bug的心态,这其实在硬件代码是很不可取的。也是一种惰性思想,学习本就是多思考,能做完美的事情就不应该因为偷懒加上瑕疵。
希望我的答案对大家的学习能有所帮助。


浙公网安备 33010602011771号