目录
本篇博客对 Verilog Language 剩余两个部分的题目写完,首先对题干先读懂是关键,然后思考如何实现并验证,这里采用先对题目解读,也就是要让我们干什么,然后直接给出答案。
分别用 assign 语句和 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
连续赋值(assign x = y;)。不能在 always 块中使用。
过程阻塞赋值:(x = y;)。只能在过程中使用。
过程非阻塞赋值:(x <= y;)。只能在过程中使用。
在组合 always 块中,使用阻塞赋值。
在时序 always 块中,使用非阻塞赋值。
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
if 语句通常创建一个 2 对 1 多路复用器,如果条件为 ture,则选择一个输入,如果条件为 false,则选择另一个输入。这等效于使用带有条件运算符的连续赋值:
assign out = (condition) ? x : y;
构建一个在 a 和 b 之间进行选择的 2 对 1 多路复用器。如果sel_b1和sel_b2都为真,请选择 b。否则,请选择 a。执行相同的操作两次,分别使用赋值语句和过程 if 语句。
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 & sel_b2) begin
out_always = b;
end
else begin
out_always = a;
end
end
endmodule
学习如何避免产生 latch, 比如在 always 块中所列举的情况没有完全,会出现你没有列举的情况时,那输出会是什么呢?Verilog的答案是:保持输出不变。这种“保持输出不变”的行为意味着需要记住当前状态,从而产生latch。组合逻辑不能保存任何状态。组合电路必须在所有条件下为所有输出分配一个值。这通常意味着始终需要为输出分配 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) begin
shut_off_computer = 1;
end
else begin
shut_off_computer = 0;
end
end
always @(*) begin
if (~arrived) begin
keep_driving = ~gas_tank_empty;
end
else begin
keep_driving = 0;
end
end
endmodule
case语句的练习。case 语句以 case 开头,每个“case 项”都以冒号结尾。
每个事例项只能执行一条语句。这意味着,如果需要多个语句,则必须使用begin结束。允许重复(和部分重叠)案例项目。使用第一个匹配的。
在本练习中,创建一个 6 对 1 多路复用器。当 sel 介于 0 和 5 之间时,选择相应的数据输入。否则,输出 0。数据输入和输出均为4位宽。
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
case(sel)
0: out = data0;
1: out = data1;
2: out = data2;
3: out = data3;
4: out = data4;
5: out = data5;
default: out = 0;
endcase
end
endmodule
优先级编码器是一种组合电路,当给定输入位矢量时,输出矢量中第一个1位的位置。例如,给定输入 8'b100 1 0000 的 8 位优先级编码器将输出 3'd4,因为 bit[4] 是第一个高位。构建 4 位优先级编码器。对于此问题,如果输入位均为零,则输出为零。请注意,4 位数字有 16 种可能的组合。
module top_module (
input [3:0] in,
output reg [1:0] pos
);
always @(*) begin
case(in)
4'b0000: pos = 0;
4'b0001: pos = 0;
4'b0010: pos = 1;
4'b0100: pos = 2;
4'b1000: pos = 3;
4'b0011: pos = 0;
4'b0110: pos = 1;
4'b1100: pos = 2;
4'b0101: pos = 0;
4'b1010: pos = 1;
4'b1001: pos = 0;
4'b0111: pos = 0;
4'b1110: pos = 1;
4'b1011: pos = 0;
4'b1101: pos = 0;
4'b1111: pos = 0;
endcase
end
endmodule
case 语句就像是按顺序检查每个情况,这是一个很大的组合逻辑函数。请注意,某些输入(例如,4'b1111)将如何匹配多个事例项。选择第一个匹配项(因此 4'b1111 匹配第一个项目,out = 0,但后面的任何一个都不匹配)。还有一个类似的案例,它将x和z视为不在乎。我看不出在casez上使用它有多大意义。数字 ? 是 z 的同义词。所以 2'bz0 与 2'b?0 相同。
module top_module (
input [7:0] in,
output reg [2:0] pos
);
always @(*) begin
casez(in)
8'bzzzzzzz1: pos = 0; //z表示不在乎这个是什么值。只需要满足后面位的情况
8'bzzzzzz10: pos = 1;
8'bzzzzz100: pos = 2;
8'bzzzz1000: pos = 3;
8'bzzz10000: pos = 4;
8'bzz100000: pos = 5;
8'bz1000000: pos = 6;
8'b10000000: pos = 7;
endcase
end
endmodule
在使用case语句时避免产生latch的方法。
为避免产生锁存器,必须在所有可能条件下为所有输出分配一个值。仅仅有一个默认的案例是不够的。必须为所有四种情况下的所有四个输出分配一个值,并在所有默认情况下分配一个值。这可能涉及大量不必要的键入。
解决此问题的一种方法是在case语句之前为输出分配一个“默认值”:
always @(*) begin
up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
case (scancode)
... // Set to 1 as necessary.
endcase
end
这种代码样式可确保在所有可能的情况下为输出分配一个值,除非case语句覆盖赋值。
提醒:逻辑合成器生成一个组合电路,其行为与代码描述的行为等效。硬件不会按顺序“执行”代码行。
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)
16'he075: up = 1'b1;
16'he072: down = 1'b1;
16'he06b: left = 1'b1;
16'he074: right = 1'b1;
default: begin
up = 1'b0;
down = 1'b0;
left = 1'b0;
right = 1'b0;
end
endcase
end
endmodule
给定四个无符号数字,找到最小值。无符号数字可以与标准比较运算符(a < b)进行比较。使用条件运算符制作双向最小电路,然后组合其中的几个以创建 4 路最小电路。可能需要一些导线向量作为中间结果。
module top_module (
input [7:0] a, b, c, d,
output [7:0] min
);
wire [7:0] smaller0;
wire [7:0] smaller1;
wire [7:0] smaller2;
assign smaller0 = (a > b)? b : a;
assign smaller1 = (c > d)? d : c;
assign smaller2 = (smaller0 > smaller1)? smaller1 : smaller0;
assign min = smaller2;
endmodule
注:也可以设计为流水线的形式,流水线的设计方法可以使系统的运行速率提高。
奇偶校验通常用作通过不完美通道传输数据时检测错误的简单方法。创建一个电路,该电路将计算 8 位字节的奇偶校验位(这将向该字节添加第 9 位)。将使用“偶数”奇偶校验,奇偶校验位只是所有8个数据位的XOR。
一个简单的连续位做异或运算。
module top_module (
input [7:0] in,
output parity
);
assign parity = ^in;
endmodule
在[99:0]中构建具有100个输入的组合电路。
有 3 个输出:
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = & in;
assign out_or = | in;
assign out_xor = ^ in;
endmodule
给定一个 100 位输入向量 [99:0],反转其位排序。
module top_module(
input [99:0] in,
output [99:0] out
);
integer i;
always @(*) begin
for (i=0;i<100;i=i+1) begin
out[i] = in[99-i];
end
end
endmodule
对输入位宽为255的数计算其各个位为 1 的个数并输出
module top_module(
input [254:0] in,
output [7:0] out
);
reg [7:0] cnt;
integer i;
always @(*) begin
cnt = 'd0;
for (i=0;i<255;i=i+1) begin
cnt = (in[i])? (cnt+1'b1):cnt;
end
end
assign out = cnt;
endmodule
通过实例化 100 个全加器来创建一个 100 位二进制行波进位加法器。加法器将两个 100 位数字和一个随身数字相加,以产生 100 位总和并执行。实际实例化全加器,还要从行波进位加法器中的每个全加器输出执行。cout[99]是最后一个全加器的最终执行。
注意对第一个全加器计算时的特殊情况。
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum
);
genvar i;
generate
for(i=0;i<100;i=i+1) begin:adder
if(i==0)
assign{cout[0],sum[0]}=a[0]+b[0]+cin;
else
assign{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];
end
endgenerate
endmodule
以一个四位的全加器模块,计算两个输入数据的相加,其位宽为400。
在这里吐槽一下 HDLBits 自带的编译器有点神经质,有些没必要的细节过度把控,而有些带有技巧性的语法又不支持...
module top_module(
input [399:0] a,b,
input cin,
output cout,
output [399:0] sum
);
wire [99:0] cin_cnt;
genvar i;
generate
for (i=0;i<100;i=i+1) begin:test
if (i == 0) begin
bcd_fadd bcd_fadd_inst(a[3:0],b[3:0],cin,cin_cnt[0],sum[3:0]);
end
else begin
bcd_fadd bcd_fadd_inst(a[4*(i+1)-1:4*i],b[4*(i+1)-1:4*i],cin_cnt[i-1],cin_cnt[i],sum[4*(i+1)-1:4*i]);
end
end
assign cout = cin_cnt[99];
endgenerate
endmodule 我想使用部分字符串搜索数组,然后获取找到该字符串的索引。例如:a=["Thisisline1","Wehaveline2here","andfinallyline3","potato"]a.index("potato")#thisreturns3a.index("Wehave")#thisreturnsnil使用a.grep将返回完整的字符串,使用a.any?将返回正确的true/false语句,但都不会返回匹配的索引找到了,或者至少我不知道该怎么做。我正在编写一段代码,该代码读取文件、查找特定header,然后返回该header的索引,以便它可以将其用作future搜索的偏移量。如果
K伙计们,所以我创建了这个赞成/反对的投票脚本(基本上就像stackoverflow上的那个),我试图向其中添加一些Ajax,这样页面就不会在您每次投票时都重新加载。我有两个Controller,一个叫grinder,一个叫votes。(磨床基本都是帖子)所以这是所有研磨机的索引(看起来像这样)这是该页面的代码。Listinggrinders"grinders/grinders")%>这就是我在views/grinders/_grinders.erb中的内容true)do|u|%>grinder.id%>"up"%>'create')%>true)do|d|%>grinder.id%>
我将restclient用于多部分表单,以将数据发送到restfulweb服务(它是Panda视频编码服务)。不过,诀窍在于我传递给restclient(Technoweenie分支)的文件来自用户提交的我自己的表单。那么,让我们来看看这个。用户将文件发布到我的Rails应用程序。在我的Controller中,它从params[:file]接收文件。然后我想使用RestClient将params[:file]传递给Panda。我在Panda服务器上遇到的错误如下。我注意到堆栈跟踪中的文件参数也在一个字符串中(我假设Panda将其转换为字符串以获得更好的堆栈跟踪)。~Startedreq
我在标准rails2.1项目中使用Test/Unit。我希望能够独立于任何特定的Controller/操作来测试分部View。好像ZenTest'sTest::Rails::ViewTestCase会有所帮助,但我无法让它工作,与view_testhttp://www.continuousthinking.com/tags/view_test类似Google出现的大部分内容似乎都已经过时了,所以我猜它并不真正适用于Rails2.1非常感谢任何帮助。谢谢,罗兰 最佳答案 我们正在使用RSpec在我们的Rails2.1项目中,我们可以做
我需要一些在ruby(1.8.6或1.8.7而不是1.9)中实现curry函数的示例。 最佳答案 下面是如何用block而不是方法来柯里化(Currying):defcurry(&block)arity=(block.arity>=0)?block.arity:-(block.arity+1)#returnanimmediatevalueiftheblockhasonereturnblock[]ifarity==0#otherwise,curryitargumentbyargumentargs=[]innermost=lambd
这个问题已经被问过很多次了,但我无法让它工作。我想像这样将多个变量传递给我的部分...这是部分material_fields.html.erb中的一行,我希望f.select预先填充Yes选项或“true”值。(有些情况下我希望它是假的)f可用并且有效,而feed不可用......我不知道为什么这不起作用。我在select语句之外尝试了,但它仍然不起作用。在这两种情况下,我都得到未定义的局部变量或方法“feed”。有人知道我的语法有什么问题吗? 最佳答案 我想通了是什么问题。我有后来我在同一个View中显然,当从一个文件渲染相同的部
我的应用有一个选择框供用户选择“地点”。如您所料,此选择框位于一个表单中。我还在页面上的某处执行了一个操作,该操作通过AJAX创建了一个新场所。创建新field后,我想更新field选择框以反射(reflect)这一点。我的解决方案是将选择框放在局部中,并从Controller中的创建操作中呈现局部。'venue/venue_select_box'%>局部看起来像这样:'Selectavenue'%>其中f是表单引用:问题是f在部分中未定义,所以我得到一个错误。一种解决方案是包括整个表格,但我觉得没有必要这样做,因为我没有更新整个表格。关于如何解决这个问题有什么想法吗?
我正在查看讨论中的一些代码并偶然发现了这个并且想知道为什么klass=self.据我所知,他们是比我更好的ruby开发人员,这一定是有充分理由的。他们为什么不调用self.remove_from_cache!(message["key"],false)?该block是否正在创建一个新范围,其中self引用MessageBus类?是否有其他示例说明您需要在Ruby中创建此类构造,或者这是主要示例?如果MessageBus.subscribe是MessageBus的一个实例(比如说m_bus.subscribe)会自己引用block中的m_bus吗?ensure_class_liste
我有一个主页,整个页面都呈现了一些部分。它也有sessionheader(登录)。部分包含已分页的书籍集。现在我想缓存这个部分,因为它每周更新一次。问题1:如何缓存特定的部分(不命中分贝)?问题2:更新时如何删除(过期)缓存内容那个书本模型? 最佳答案 您正在寻找fragmentcaching这里,发生在View层。片段缓存和存储内容的过期非常容易做到。您有一个图书list,假设您的View看起来有点像这样:要为这一位启用缓存,只需将其包装在cache中:当然,这不会为缓存命名或对它做任何特别的事情...虽然Rails会自动为这个缓
问题我试图在我的View中重用错误消息block。下面是positions/_error_messages.html.erb中写的blockTheformcontains.*问题是我必须在每个模型中创建类似的部分View,这有点像用不同的对象重复相同的代码,即@user、@client等。补救措施我在共享文件夹shared/_error_messages.html.erb中创建了一个erb并编写了以下代码。Theformcontains.*然后在查看文件中。positions/new.html.erb我写了下面的代码这意味着现在我可以在所有创建和更新操作中使用相同的代码。我想知道,这样