(1}驱动与赋值:
wire类型是被驱动的,该值不被保存,再任一仿真步进上都需要重新计算。
reg类型是被赋值的,再仿真过程中被一直保持,直到下一个赋值出现。
wire A_xor_wire;
assign #1 A_xor_wire = eq0 ^ eq1;
两者描述目的一样,但第一个实际是连续驱动的过程,在仿真的任意时刻A_xor_wire的值为eq0与eq1的异或;第二个只在eq0或eq1发生改变时,才会将计算的值赋给A_xor_wire,在其他时刻A_xor_wire的值需要被保持。
连续赋值assign语句左侧必须是net类型(如wire类型),过程赋值always块中的赋值语句左侧必须是reg类型。
reg A_xor_wire;
always @ (eq0 or eq1)
A_xor_wire = #1 eq0 ^ eq1;
{2}若无特别定义,input,output都默认为wire类型
即module (input a output c);默认为module (input wire a output wire c);
(3)xor 异或;xnor同或(异或非)
(4)vector向量的定义:
如:wire [3:0] vec1;
向量的维度在向量名之前。
(4)implicit nets:
wire [2:0] a,c;
assign a = 3'b001;
assign b = a; // b = 1; 产生implicit net
assign c = b; // c = 001; bug
未声明时b默认为为一位wire,所以要把第三个赋值语句会报错;
添加`default_nettype none指令会使上面第二个语句就开始报错,使bug更容易发现。
(5)
数组array
reg [7:0] vec1 [254:0]; // 255个元素,每个为8位的reg
reg vec2 [254:0]; //255个元素,每个为1位的reg
(6)
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
//and(out_and,in[3],in[2],in[1],in[0]);
//assign out_and = in[3] & in[2] & in[1] & in[0];
assign out_and = & in;
//or(out_or,in[3],in[2],in[1],in[0]);
//assign out_or = in[3]|in[2]|in[1]|in[0];
assign out_or = |in;
//xor(out_xor,in[3],in[2],in[1],in[0]);
//assign out_xor = in[3] ^ in[2]^in[1]^in[0];
assign out_xor = ^in;
endmodule
(7)按位操作符:
~ : ~m,将m每个位取反。
& : m & n,将m每个位与n相应位相与。
| : m | n,将m每个位与n相应位相或。
^ : m ^ n,将m每个位与n相应位相异或。
~^ 或 ^~ : m ~^ n或m ^~ n,将m每个位与n相应位相异或非。
规约操作符:
& : &m,将m所有位相与(1位结果)。
~& : ~&m,将m所有位相与非(1位结果)。
| : |m,将m所有位相或(1位结果)。
~| : ~|m,将m所有位相或非(1位结果)。
^ : ^m,将m所有位相异或(1位结果)。
~*或^~ : ~^m或^~m,将m所有位相异或非(1位结果)。
(8)向量的级联
如 input [15:0] in;
output [23:0] out;
assign out[15:0] = {in[7:0] , in[15:8]};
assign {out[15:8] , out[7:0]} = in;
以上两个赋值语句描述的结果相同,都是将in的两个字节交换赋值给out的低16位。
assign out = {in[7;0] , in[15:8]};
这条赋值语句为了匹配左边out的24位,右边需要扩展到24位,将[23:16]赋值0,所以最后out[15:0]与前两条相同,out[23:16]每位都为0,而前两句对out[23:16]没有赋值。
如
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );
// assign { ... } = { ... };
assign {w,x,y,z} = {a,b,c,d,e,f,2'b11};
endmodule
如
建立一个电路,将8位数字扩展到32位。这需要连续24个符号位的拷贝(即复制位[7]24次),然后是8位数字本身
module top_module (
input [7:0] in,
output [31:0] out );//
//assign out = {{24{in[7]}},in};
assign out = in[7]?{{24{1'b1}},in}:{{24{1'b0}},in};
endmodule
————————————————
版权声明:本文为CSDN博主「杰之行」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haojie_duan/article/details/113245637
(9)模块实例化
通过位置或名称将要调用模块的模块的wire与被调用的模块的端口连接起来:
module mod_a (input in1, input in2, output out);
//module body
endmodule
现在top_module中调用mod_a:
module top_module (input a, input b, output out);
// mod_a instance1 (a, b, out); 此为位置,实例化一个mod_a类型的模块,将它命名为“instance1”,其端口位置必须与mod_a的端口位置严格对应。
mod_a instance2 (.out(out),
.in1(a),
.in2(b)); //此为名称,中略,这种方法端口位置不影响
endmodule
(10)always用法,case用法
例:
always @(*) begin
case (sel)
2'b00:q = d; //case后只能跟一个赋值语句。
2'b01:q = q0;
2'b10:q = q1;
2'b11:q = q2;
default:; //指的是上面没有说明到的其他情况
endcase
end
always @后如果是“*”那么说明是组合逻辑电路,如果是posedge,negedge就是时序逻辑电路。
(11)有三种赋值方法
1)对于时序逻辑,即always模块的敏感表为沿敏感信号(多为时钟或复位的正沿或负沿),统一用非阻塞赋值。
2)对于always模块的敏感表为电平敏感信号的组合逻辑,统一用阻塞赋值。
3)对于assign描述的组合逻辑,称为连续赋值语句,统一用阻塞赋值,变量被定义为wire型信号。
例:
reg [3:0] cnt_out_plus;
always @(cnt_out)
cnt_out_plus = cnt_out + 1;
注意:1)虽然cnt_out_plus为reg类型,但always模块的敏感表为电平敏感信号,所以为纯组合逻 辑。
2)为什么不用 cnt_out = cnt_out + 1; 因为这样会产生组合逻辑环,为大忌。
时序的always块的输出不会像其他两个一样立即可见,而是会在输出处会生成一个寄存器,在下一个敏感源到来时才能看到这个输出。也就是说时序的always块的输出是延时的。
(12)always块里的if语句
always @(*) begin if (condition) begin out = x; end else begin out = y; end end
(12.1)if 语句注意
if(条件..1){undefined
要执行的语句;
}
if(条件..2){undefined
要执行的语句
}
双if是每一个if都会进行判断,依次对if进行判断,互相之间不会影响;
if(条件..1){undefined
执行的语句
}else if(条件..2){undefined
执行的语句
}
这个if和else if 之间是有联系的,当不满足if中的条件的时候,就会去执行else if ,如果if中的条件已经满足了,就不会去判断else if中的条件了
————————————————
版权声明:本文为CSDN博主「libin_gogogo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/libin_gogogo/article/details/78265973
(13)使用带有条件运算符的连续赋值
assign out = (condition) ? x : y;
(14)case-z 的使用
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
z代表不关心的值。有时会用?或x代替z。
(15)奇偶校验电路可以用异或来实现:
偶数个1异或的结果总为0,奇数个1异或的结果总为1。
(16)倒序题 for循环的使用
注意每位与1异或只能实现每位值反转,并不能实现倒序。
如 4c...63倒序
0100 1100 ... 0110 0011
倒序:1100 0110 ... 0011 0010
与1异或: 1011 0011 ... 1001 1100
所以可用for循环实现倒序,循环次数变量要声明为integer
如
在always组合逻辑块中使用:
integer i;
always @(*) begin
for (i=0;i<=99;i++)
out[i] = in[99-i];
end
也可以在assign语句中使用,但要用generate包起来:
如
generate
genvar i;
for (i=0;i<=99;i++) begin:reverse
assign out[i] = in[99-i];
end
endgenerate
(17)generate
可用于对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时
generate语法
- 定义genvar,作为generate种的循环变量。
- generate语句中定义的for语句,必须要有begin,为后续增加标签做准备。
- begin必须要有名称,也就是必须要有标签,因为标签会作为generate循环的实例名称。
generate语句有generate-for,generate-if,generate-case三种语句。
generate-for语句
(1) 必须有genvar关键字定义for语句的变量。
(2)for语句的内容必须加begin和end(即使就一句)。
(3)for语句必须有个名字。
例题:100位加法器
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
//always @(*) begin
// {cout[0],sum[0]} = a[0] + b[0] + cin;
//end
//integer i;
//always @(*) begin
// for (i=1;i<=99;i++) begin
// {cout[i],sum[i]} = a[i] + b[i] + cout[i-1];
// end
//end
generate
genvar i;
for (i=0;i<=99;i++) begin:adder
if (i == 0) begin
fulladder fulladder_inst (a[0],b[0],cin,cout[0],sum[0]);
end
else begin
fulladder fulladder_inst (a[i],b[i],cout[i-1],cout[i],sum[i]);
end
end
endgenerate
endmodule
module fulladder (input a,input b,input cin,output cout,output sum);
assign {cout,sum} = a + b + cin;
endmodule
(18)verilog与c的不同导致的错误
例一:Bcdadd100
You are provided with a BCD one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
module bcd_fadd ( input [3:0] a, input [3:0] b, input cin, output cout, output [3:0] sum );
Instantiate 100 copies of bcd_fadd to create a 100-digit BCD ripple-carry adder. Your adder should add two 100-digit BCD numbers (packed into 400-bit vectors) and a carry-in to produce a 100-digit sum and carry out.
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [99:0] c;
genvar i;
generate
for (i=0;i<=99;i++) begin:adder
if (i==0) begin
bcd_fadd bcd_fadd_inst (a[3:0],b[3:0],cin,c[0],sum[3:0]);
end
else begin
bcd_fadd bcd_fadd_inst (a[4*i+3:4*i],b[4*i+3:4*i],c[i-1],c[i],sum[4*i+3:4*i]); //
end
end
assign cout = c[99];
endgenerate
endmodule
例二:Mux256to1v
Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel=0 should select bits in[3:0], sel=1 selects bits in[7:4], sel=2 selects bits in[11:8], etc.
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
always @(*) begin
out = in[4*sel+3:4*sel]; //报错
end
endmodule
例二“4*sel+3:4*sel”这么写会报错“sel不是常量”,而例一中情况则不会。
例二有两种修改方法:
1)out = out = in[4*sel+3 -:4];
表示in的序号4*sel+3以下(包括自己在内)的连续4位。
同理也可以写成:
out = out = in[4*sel +:4];
表示in的序号4*sel以上(包括自己在内)的连续4位。
2)out = {in[4*sel+3],in[4*sel+2],in[4*sel+1],in[4*sel]};
直接拆开把四位级联起来,不用“:”的方式表示。
(19)溢出的判断(补码运算)
计算结果最高位与次高位的进位情况,如果最高位和次高位同时产生进位,即所谓双进位,则这种进位属于允许的自然丢弃。如果只有最高位或者只有次高位产生进位,即只有单进位,则这种进位属于溢出。
所以overflow = cout[最高位] ^ cout[最高位-1];
或者:
由于只有两个正数(负数)相加才可能发生溢出。
所以overflow = a[最高位] & b[最高位] & ~sum[最高位] | ~a[最高位] & ~b[最高位] & sum[最高位]
(20)同步复位,异步复位
(47条消息) 三种复位方式: 同步复位、异步复位、异步复位同步释放_坚持-CSDN博客_异步复位同步释放
同步复位:只在时钟上升沿(如果电路是下降沿有效,那么复位也是下降沿有效)时才有效。
always @ (posedge clk) begin
if (!Rst_n)
...
end
异步复位:无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。
always @ (posedge clk,negedge Rst_n) begin
if (!Rst_n)
...
end
(21)建立时间,保持时间,恢复时间,去除时间。
触发器再时钟有效沿(上升沿或下降沿)来临时对数据进行采样,但实际器件无法做到瞬间完成数据的采样,需要数据再时钟沿前后稳定一段时间,即引入建立时间与保持时间的概念。
1)建立时间Tsu(Setup):时钟有效沿来临之前数据必须保持稳定的最小时间。
2)保持时间Th(Hold):时钟有效沿来临之后数据必须保持稳定的最小时间。
与同步电路中的建立时间,保持时间类似,异步控制信号(如寄存器的异步复位信号)同样需要与时钟满足recovery time和removal time才能有效进行复位操作,防止输出亚稳态。
3)恢复时间(recovery):撤销复位时,恢复到非复位状态的异步控制信号的电平必须在时钟有效沿到来前保持不变的最小时间。
4)去除时间(removal):复位时,已处于复位状态的异步控制信号的电平必须在时钟有效沿后继续保持不变的最小时间。
(22)边沿检测
Edgedetect
For each bit in an 8-bit vector, detect when the input signal changes from 0 in one clock cycle to 1 the next (similar to positive edge detection). The output bit should be set the cycle after a 0 to 1 transition occurs.
Here are some examples. For clarity, in[1] and pedge[1] are shown separately.
module top_module (
input clk,
input [7:0] in,
output reg [7:0] pedge
);
reg [7:0] in_1;
always @(posedge clk) begin
in_1 <= in;
pedge <= in & ~in_1;
end
endmodule
“in_1 <= in;” //将本次输入电平保存至in_1,因为为非阻塞赋值,所以会有一个时钟周期的延时
“pedge <= in & ~in_1;” //将本次输入电平与前一次的保存电平的反进行与操作,探测上升沿
另外写成这样也可以:
always @(posedge clk) begin
in_1 <= in;
end
always @(posedge clk) begin
pedge <= in & ~in_1;
end
(23)上升(下降)沿捕获锁存
探测输入信号每一位的下降沿,若其中部分位有下降沿,则下一周期输出对应位高电平并锁存,直到复位信号reset到来才复位为0。
注意:下降沿捕获均为按位操作,其中一位下降沿只影响对应位的输出,其他位不受影响。
如果这样写会出错:
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_1;
always @(posedge clk) begin
if (reset) begin
out <= 32'b0;
end
else begin
in_1 <= in;
out <= ~in & in_1 | out;
end
end
endmodule
因为若是reset为1,那么在此时钟周期内 in_1 <= in;不会执行,在红色箭头处,reset复位,执行out赋值0,在此时钟周期不再执行in_1 <= in,直到蓝色箭头处,才重新执行,因此此处in_1值为10,而不是0,进而造成out值错误。
所以:
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_1;
always @(posedge clk) begin
in_1 <= in;
end
always @(posedge clk) begin
if (reset) begin
out <= 32'b0;
end
else begin
out <= ~in & in_1 | out;
end
end
endmodule
(24)clk双边沿触发Dualedge
You're familiar with flip-flops that are triggered on the positive edge of the clock, or negative edge of the clock. A dual-edge triggered flip-flop is triggered on both edges of the clock. However, FPGAs don't have dual-edge triggered flip-flops, and always @(posedge clk or negedge clk) is not accepted as a legal sensitivity list.
Build a circuit that functionally behaves like a dual-edge triggered flip-flop:
方法一:
module top_module (
input clk,
input d,
output q
);
reg q_pedge;
reg q_nedge;
always @(posedge clk) begin
q_pedge <= d;
end
always @(negedge clk) begin
q_nedge <= d;
end
assign q = clk?q_pedge:q_nedge;
endmodule
方法二:
module top_module (
input clk,
input d,
output q
);
reg q_d1;
reg q_d2;
always @(posedge clk) begin
q_d1 <= d ^ q_d2;
end
always @(negedge clk) begin
q_d2 <= d ^ q_d1;
end
assign q = q_d1 ^ q_d2;
endmodule
(25)计数器Exams/ece241 2014 q7b
From a 1000 Hz clock, derive a 1 Hz signal, called OneHertz, that could be used to drive an Enable signal for a set of hour/minute/second counters to create a digital wall clock. Since we want the clock to count once per second, the OneHertz signal must be asserted for exactly one cycle each second. Build the frequency divider using modulo-10 (BCD) counters and as few other gates as possible. Also output the enable signals from each of the BCD counters you use (c_enable[0] for the fastest counter, c_enable[2] for the slowest).
The following BCD counter is provided for you. Enable must be high for the counter to run. Reset is synchronous and set high to force the counter to zero. All counters in your circuit must directly use the same 1000 Hz signal.
module bcdcount ( input clk, input reset, input enable, output reg [3:0] Q );
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
); //
//wire [3:0] q0,q1,q2;
//assign c_enable[0] = 1'b1;
//assign c_enable[1] = q0 == 4'd9;
//assign c_enable[2] = q1 == 4'd9 && q0 == 4'd9;
//assign OneHertz = q2 == 4'd9 && q1 == 4'd9 && q0 == 4'd9;
// bcdcount counter0 (clk, reset, c_enable[0],q0);
// bcdcount counter1 (clk, reset, c_enable[1],q1);
// bcdcount counter2 (clk, reset, c_enable[2],q2);
wire [11:0] q;
assign c_enable = {q[7:4] == 4'd9 && q[3:0] == 4'd9, q[3:0] == 4'd9 , 1'b1};
//assign c_enable = {q[7:0] == 8'h99, q[3:0] == 4'd9 , 1'b1};
assign OneHertz = q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9;
//assign OneHertz = q[11:0] == 12'h999;
bcdcount counter0 (clk, reset, c_enable[0],q[3:0]);
bcdcount counter1 (clk, reset, c_enable[1],q[7:4]);
bcdcount counter2 (clk, reset, c_enable[2],q[11:8]);
endmodule
(26)parameter的使用
(49条消息) Verilog中的parameter_qq_16923717的博客-CSDN博客_parameter verilog
(27)Count clock
Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).
reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.
The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
wire [1:0] ena_ss;
wire [1:0] ena_mm;
wire ena_hh_r;
wire [7:0] hh_r;
assign ena_ss[0] = ena && (ss[3:0] == 4'h9);
assign ena_ss[1] = ena_ss[0] && (ss[7:4] == 4'h5);
assign ena_mm[0] = ena_ss[1] && (mm[3:0] == 4'h9);
assign ena_mm[1] = ena_mm[0] && (mm[7:4] == 4'h5);
assign ena_hh_r = ena_mm[1] && (hh_r[3:0] == 4'hb);
BCD_count #(.START(4'h0),.END(4'h9)) ss9 (clk,reset,ena,ss[3:0]);
BCD_count #(.START(4'h0),.END(4'h5)) ss5 (clk,reset,ena_ss[0],ss[7:4]);
BCD_count #(.START(4'h0),.END(4'h9)) mm9 (clk,reset,ena_ss[1],mm[3:0]);
BCD_count #(.START(4'h0),.END(4'h5)) mm5 (clk,reset,ena_mm[0],mm[7:4]);
BCD_count #(.START(4'h0),.END(4'hb)) hhb (clk,reset,ena_mm[1],hh_r[3:0]);
BCD_count #(.START(4'h0),.END(4'h1)) hh1 (clk,reset,ena_hh_r,hh_r[7:4]);
assign pm = (hh_r[7:4] == 4'h1);
assign hh[7:0] = (hh_r[3:0] == 4'h0) ? 8'h12 : ((hh_r[3:0] > 4'h9) ? {4'h1,hh_r[3:0] - 4'ha}:{4'h0,hh_r[3:0]});
endmodule
module BCD_count (input clk,
input reset,
input ena,
output reg [3:0] q);
parameter START = 4'h0, END = 4'h9;
always @(posedge clk) begin
if (reset)
q <= START;
else if (ena)
q <= (q == END) ? START:q + 4'h1;
else
q <= q;
end
endmodule
方法二:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
always @(posedge clk) begin
if (reset) begin
pm <= 1'h0;
ss[7:0] <= 8'h0;
mm[7:0] <= 8'h0;
hh[7:0] <= 8'h12;
end
else if (ena) begin
if (ss[3:0] != 4'h9) begin
ss[3:0] <= ss[3:0] + 4'h1;
end
else begin
ss[3:0] <= 4'h0;
ss[7:4] <= ss[7:4] + 4'h1;
if (ss[7:4] == 4'h5) begin
ss[7:4] <= 4'h0;
mm[3:0] <= mm[3:0] + 4'h1;
if (mm[3:0] == 4'h9) begin
mm[3:0] <= 4'h0;
mm[7:4] <= mm[7:4] + 4'h1;
if (mm[7:4] == 4'h5) begin
mm[7:4] <= 4'h0;
hh[3:0] <= hh[3:0] + 4'h1;
if (hh[3:0] == 4'h9) begin
hh[3:0] = 4'h0;
hh[7:4] <= hh[7:4] + 4'h1;
end
if (hh[7:4] == 4'h1 && hh[3:0] == 4'h1) begin
pm <= ~pm;
hh[3:0] <= hh[3:0] + 4'h1;
end
if (hh[7:4] == 4'h1 && hh[3:0] == 4'h2) begin
hh[7:0] <= {4'h0,4'h1};
end
end
end
end
end
end
end
endmodule
注意:在
if (mm[7:4] == 4'h5) begin
mm[7:4] <= 4'h0;
hh[3:0] <= hh[3:0] + 4'h1;
if (hh[3:0] == 4'h9) begin
hh[3:0] = 4'h0;
hh[7:4] <= hh[7:4] + 4'h1;
end
if (hh[7:4] == 4'h1 && hh[3:0] == 4'h1) begin
pm <= ~pm;
hh[3:0] <= hh[3:0] + 4'h1;
end
if (hh[7:4] == 4'h1 && hh[3:0] == 4'h2) begin
hh[7:0] <= {4'h0,4'h1};
end
end
处,如果之前reset过,那么hh[7:0] = 8'h12,在红线处hh[3:0]加4'h1,那么进入下面if判断时hh[7:0] = 8'h13,使得hh[7:0]输出13,14,15等等,为什么不是这样?
因为hh[3:0] <= hh[3:0] + 4'h1;为非阻塞赋值,虽然进入if判断之前已经做了加法,但其输出要到下一个敏感表才生效,进入if判断的仍是原来的值。
关于非阻塞赋值和begin end块的问题 - FPGA/ASIC/IC前端设计 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
方法二更新版本:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
always @(posedge clk) begin
if (reset) begin
pm <= 1'h0;
ss[7:0] <= 8'h0;
mm[7:0] <= 8'h0;
hh[7:0] <= 8'h12;
end
else if (ena) begin
if (ss[3:0] == 4'h9) begin
ss[3:0] <= 4'h0;
if (ss[7:4] == 4'h5) begin
ss[7:4] <= 4'h0;
if (mm[3:0] == 4'h9) begin
mm[3:0] <= 4'h0;
if (mm[7:4] == 4'h5) begin
mm[7:4] <= 4'h0;
if (hh[3:0] == 4'h9) begin
hh[3:0] = 4'h0;
hh[7:4] <= hh[7:4] + 4'h1;
end
else if (hh[7:4] == 4'h1 && hh[3:0] == 4'h1) begin
pm <= ~pm;
hh[3:0] <= hh[3:0] + 4'h1;
end
else if (hh[7:4] == 4'h1 && hh[3:0] == 4'h2) begin
hh[7:0] <= {4'h0,4'h1};
end
else
hh[3:0] <= hh[3:0] + 4'h1;
end
else
mm[7:4] <= mm[7:4] + 4'h1;
end
else
mm[3:0] <= mm[3:0] + 4'h1;
end
else ss[7:4] = ss[7:4] + 4'h1;
end
else
ss[3:0] <= ss[3:0] + 4'h1;
end
end
endmodule
(28)Exams/ece241 2013 q12
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
reg [7:0] Q;
always @(posedge clk) begin
if (enable) begin
Q <= {Q[6:0],S};
end
//case({A,B,C})
//3'b000: Z = Q[0];
//3'b001: Z = Q[1];
//3'b010: Z = Q[2];
//3'b011: Z = Q[3];
//3'b100: Z = Q[4];
//3'b101: Z = Q[5];
//3'b110: Z = Q[6];
//3'b111: Z = Q[7];
//endcase
end
assign Z = Q[{A,B,C}];
endmodule
如果用注释里的代码如上图所示输出会落后一个时钟周期,因为它是时序逻辑的,触发条件为时钟上升沿,而连续赋值语句是组合逻辑的。
根据题目所示,这是三输入查找表,所以此多路复用器也应该是组合逻辑的,而不是时序的。