【HDLBits 刷题 13】Buliding Larger Circuits

2023-11-10

目录

写在前面

Buliding Larger Circuits

count1k

shiftcount

fsm seq

fsmshift

fsm

fancytimer

fsm onehot


写在前面

以下的解题方法不一定为最佳解决方案,有更好的方法欢迎提出,共同学习,共同进步!

Buliding Larger Circuits

count1k

构建一个计数从 0 到 999(包括 0 和 999)的计数器,周期为 1000 个周期。复位输入是同步的,应将计数器复位为0。

module top_module (
    input           clk,
    input           reset,
    output [9:0]    q
);

always @(posedge clk) begin
	if (reset) begin
		q <= 'd0;
	end
	else if (q=='d999) begin
		q <= 'd0;
	end
	else begin
		q <= q + 'd1;
	end
end

endmodule

shiftcount

这是一系列五个练习中的第一个组件,该练习从几个较小的电路中构建一个复杂的计数器。

构建一个四位移位寄存器,该寄存器也可用作向下计数器。当shift_ena为 1 时,首先以最高有效位移位。当count_ena为1时,移位寄存器中的当前数字将递减。由于整个系统不使用shift_ena和count_ena,因此如果两个控制输入均为1,则电路的作用无关紧要(这主要意味着哪种情况获得更高的优先级并不重要)。

module top_module (
    input           clk,
    input           shift_ena,
    input           count_ena,
    input           data,
    output [3:0]    q
);

always @(posedge clk) begin
	if (shift_ena) begin
		q <= {q[2:0],data};
	end
	else if (count_ena) begin
		q <= q - 'd1;
	end
	else begin
		q <= q;
	end
end

endmodule

fsm seq

这是一系列五个练习中的第二个组件,该练习从几个较小的电路中构建一个复杂的计数器。

构建一个在输入位流中搜索序列 1101 的有限状态机。找到序列后,应将 start_shifting 设置为 1,直到重置。陷入最终状态的目的是模拟在尚未实现的更大的FSM中进入其他状态。我们将在接下来的几个练习中扩展此 FSM。

module top_module (
    input      clk,
    input      reset,      // Synchronous reset
    input      data,
    output     start_shifting
);

//状态申明
parameter  IDLE    =  'd1;
parameter  A_1     =  'd2;
parameter  B_1     =  'd3;
parameter  C_0     =  'd4;
parameter  D_1     =  'd5;

//现态和次态
reg  [2:0]   state;
reg  [2:0]   next_state;

//状态机第一段,状态初始化,时序逻辑非阻塞赋值
always @(posedge clk) begin
	if (reset) begin
		state <= IDLE;
	end
	else begin
		state <= next_state;
	end
end

//状态机第二段,状态跳转,阻塞赋值
always @(*) begin
	next_state = state;
	case(state)
		IDLE: begin
			if (data) begin
				next_state = A_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		A_1: begin
			if (data) begin
				next_state = B_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		B_1: begin
			if (~data) begin
				next_state = C_0;
			end
			else begin
				next_state = B_1;
			end
		end
		C_0: begin
			if (data) begin
				next_state = D_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		D_1: begin
			next_state = D_1;
		end
		default: begin
			next_state = IDLE;
		end
	endcase
end

//状态机第三段,结果输出,组合逻辑
assign start_shifting = (state==D_1);

endmodule

fsmshift

这是一系列五个练习中的第三个组件,该练习从几个较小的电路中构建一个复杂的计数器。

作为用于控制移位寄存器的FSM的一部分,我们希望能够在检测到正确的位模式时使移位寄存器精确4个时钟周期,考虑前面的处理序列检测,因此 FSM 的这一部分仅处理启用移位寄存器 4 个周期。

每当FSM复位时,置位shift_ena 4个周期,然后永远为0(直到复位)。

module top_module (
    input      clk,
    input      reset,      // Synchronous reset
    output     shift_ena
);

reg  [1:0]  cnt;

always @(posedge clk) begin
	if (reset) begin
		cnt <= 'd0;
	end
	else begin
		cnt <= cnt + 'd1;
	end
end

always @(posedge clk) begin
	if (reset) begin
		shift_ena <= 'd1;
	end
	else if (cnt=='d3) begin
		shift_ena <= 'd0;
	end
	else begin
		shift_ena <= shift_ena;
	end
end

endmodule

fsm

这是一系列五个练习中的第四个组件,该练习从几个较小的电路中构建一个复杂的计数器。

想要创建一个计时器,

  1. 在检测到特定模式 (1101) 时启动,
  2. 再移位 4 位,以确定延迟的持续时间,
  3. 等待计数器完成计数,以及
  4. 通知用户并等待用户确认计时器。

在这个问题中,只实现控制计时器的有限状态机。此处不包括数据路径(计数器和某些比较器)。

串行数据在数据输入引脚上可用。当接收到模式1101时,状态机必须断言输出shift_ena正好4个时钟周期。

之后,状态机断言其计数输出以指示它正在等待计数器,并等待输入done_counting为高电平。

此时,状态机必须断言 done 以通知用户计时器已超时,并等到输入 ack 为 1,然后重置以查找下一个匹配的开始序列 (1101)。

状态机应重置为开始搜索输入序列1101的状态。

下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明,密克罗尼西亚联邦不应关心该周期中的特定输入信号。例如,一旦检测到 1101 模式,FSM 将不再查看数据输入,直到完成其他所有操作后恢复搜索。

module top_module (
    input         clk,
    input         reset,      // Synchronous reset
    input         data,
    input         ack,
    input         done_counting, 
    output        shift_ena,
    output        counting,
    output        done
);

//状态申明
parameter  IDLE    =  'd1;
parameter  A_1     =  'd2;
parameter  B_1     =  'd3;
parameter  C_0     =  'd4;
parameter  CNT_1   =  'd5;
parameter  CNT_2   =  'd6;
parameter  CNT_3   =  'd7;
parameter  CNT_4   =  'd8;
parameter  CNT     =  'd9;
parameter  WAIT    =  'd10;

//现态和次态
reg  [3:0]   state;
reg  [3:0]   next_state;

//状态机第一段,状态初始化,时序逻辑非阻塞赋值
always @(posedge clk) begin
	if (reset) begin
		state <= IDLE;
	end
	else begin
		state <= next_state;
	end
end

//状态机第二段,状态跳转,阻塞赋值
always @(*) begin
	next_state = state;
	case(state)
		IDLE: begin
			if (data) begin
				next_state = A_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		A_1: begin
			if (data) begin
				next_state = B_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		B_1: begin
			if (~data) begin
				next_state = C_0;
			end
			else begin
				next_state = B_1;
			end
		end
		C_0: begin
			if (data) begin
				next_state = CNT_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		CNT_1: begin
			next_state = CNT_2;
		end
		CNT_2: begin
			next_state = CNT_3;
		end
		CNT_3: begin
			next_state = CNT_4;
		end
		CNT_4: begin
			next_state = CNT;
		end
		CNT: begin
			if (done_counting) begin
				next_state = WAIT;
			end
			else begin
				next_state = CNT;
			end
		end
		WAIT: begin
			if (ack) begin
				next_state = IDLE;
			end
			else begin
				next_state = WAIT;
			end
		end
		default: begin
			next_state = IDLE;
		end
	endcase
end

//状态机第三段,结果输出,组合逻辑
assign shift_ena = (state==CNT_1) | (state==CNT_2) | (state==CNT_3) | (state==CNT_4);
assign counting = state==CNT;
assign done = state==WAIT;

endmodule

fancytimer

这是一系列五个练习中的第五个组件,该练习从几个较小的电路中构建一个复杂的计数器。

想要创建一个具有一个输入的计时器:

  1. 当检测到特定输入模式 (1101) 时启动,
  2. 再移位 4 位,以确定延迟的持续时间,
  3. 等待计数器完成计数,以及
  4. 通知用户并等待用户确认计时器。

串行数据在数据输入引脚上可用。当接收到码型1101时,电路必须在接下来的4位中移位,最高有效位在先。这 4 位决定了定时器延迟的持续时间。我把它称为延迟[3:0]。

之后,状态机断言其计数输出以指示它正在计数。状态机必须精确计数(延迟[3:0] + 1)* 1000个时钟周期。例如,delay=0 表示计数 1000 个周期,delay=5 表示计数 6000 个周期。同时输出当前剩余时间。这应该等于延迟 1000 个周期,然后延迟-1 表示 1000 个周期,依此类推,直到 0 表示 1000 个周期。当电路不计数时,计数[3:0]输出是“不在乎”(任何值都方便你实现)。

此时,电路必须断言完成以通知用户计时器已超时,并等到输入ack为1,然后重置以查找下一个出现的开始序列(1101)。

电路应复位到开始搜索输入序列1101的状态。

下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明,密克罗尼西亚联邦不应关心该周期中的特定输入信号。例如,一旦读取了1101和延迟[3:0],电路就不再查看数据输入,直到完成其他所有操作后恢复搜索。在本例中,电路计数为 2000 个时钟周期,因为延迟 [3:0] 值为 4'b0001。最后几个周期以延迟[3:0] = 4'b1110开始另一个计数,这将计数15000个周期。

module top_module (
    input           clk,
    input           reset,      // Synchronous reset
    input           data,
    input           ack,
    output [3:0]    count,
    output          counting,
    output          done
);

//状态申明
parameter  IDLE      =  'd1;
parameter  A_1       =  'd2;
parameter  B_1       =  'd3;
parameter  C_0       =  'd4;
parameter  SHIFT_1   =  'd5;
parameter  SHIFT_2   =  'd6;
parameter  SHIFT_3   =  'd7;
parameter  SHIFT_4   =  'd8;
parameter  CNT       =  'd9;
parameter  WAIT      =  'd10;

//现态和次态
reg  [3:0]   state;
reg  [3:0]   next_state;
reg  [3:0]   delay;
reg  [15:0]  delay_cnt;
reg  [3:0]   delay_num;
wire         delay_cnt_done;

//当计数到设定的计数值时,将延时计数完成标志信号拉高
assign  delay_cnt_done  =  (delay_cnt == ((delay + 'd1) * 'd1000))?'d1:'d0;

//状态机第一段,状态初始化,时序逻辑非阻塞赋值
always @(posedge clk) begin
	if (reset) begin
		state <= IDLE;
	end
	else begin
		state <= next_state;
	end
end

//状态机第二段,状态跳转,阻塞赋值
always @(*) begin
	next_state = state;
	case(state)
		IDLE: begin
			if (data) begin
				next_state = A_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		A_1: begin
			if (data) begin
				next_state = B_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		B_1: begin
			if (~data) begin
				next_state = C_0;
			end
			else begin
				next_state = B_1;
			end
		end
		C_0: begin
			if (data) begin
				next_state = SHIFT_1;
			end
			else begin
				next_state = IDLE;
			end
		end
		SHIFT_1: begin
			next_state = SHIFT_2;
			delay[3]   = data;
		end
		SHIFT_2: begin
			next_state = SHIFT_3;
			delay[2]   = data;
		end
		SHIFT_3: begin
			next_state = SHIFT_4;
			delay[1]   = data;
		end
		SHIFT_4: begin
			next_state = CNT;
			delay[0]   = data;
		end
		CNT: begin
			if (delay_cnt_done) begin
				next_state = WAIT;
			end
			else begin
				next_state = CNT;
			end
		end
		WAIT: begin
			if (ack) begin
				next_state = IDLE;
			end
			else begin
				next_state = WAIT;
			end
		end
		default: begin
			next_state = IDLE;
		end
	endcase
end

//delay_cnt
always @(posedge clk) begin
	if (reset) begin
		delay_cnt <= 'd0;
	end
	else if (next_state == WAIT) begin
		delay_cnt <= 'd0;
	end
	else if (next_state == CNT) begin
		delay_cnt <= delay_cnt + 'd1;
	end
	else begin
		delay_cnt <= delay_cnt;
	end
end

//对于延时计数的范围值,确定具体的count值
always @(*) begin
	if (delay_cnt <= 'd1000) begin
		delay_num = 'd0;
	end
	else if (delay_cnt > 'd1000 && delay_cnt <= 'd2000) begin
		delay_num = 'd1;
	end
	else if (delay_cnt > 'd2000 && delay_cnt <= 'd3000) begin
		delay_num = 'd2;
	end
	else if (delay_cnt > 'd3000 && delay_cnt <= 'd4000) begin
		delay_num = 'd3;
	end
	else if (delay_cnt > 'd4000 && delay_cnt <= 'd5000) begin
		delay_num = 'd4;
	end
	else if (delay_cnt > 'd5000 && delay_cnt <= 'd6000) begin
		delay_num = 'd5;
	end
	else if (delay_cnt > 'd6000 && delay_cnt <= 'd7000) begin
		delay_num = 'd6;
	end
	else if (delay_cnt > 'd7000 && delay_cnt <= 'd8000) begin
		delay_num = 'd7;
	end
	else if (delay_cnt > 'd8000 && delay_cnt <= 'd9000) begin
		delay_num = 'd8;
	end
	else if (delay_cnt > 'd9000 && delay_cnt <= 'd10000) begin
		delay_num = 'd9;
	end
	else if (delay_cnt > 'd10000 && delay_cnt <= 'd11000) begin
		delay_num = 'd10;
	end
	else if (delay_cnt > 'd11000 && delay_cnt <= 'd12000) begin
		delay_num = 'd11;
	end
	else if (delay_cnt > 'd12000 && delay_cnt <= 'd13000) begin
		delay_num = 'd12;
	end
	else if (delay_cnt > 'd13000 && delay_cnt <= 'd14000) begin
		delay_num = 'd13;
	end
	else if (delay_cnt > 'd14000 && delay_cnt <= 'd15000) begin
		delay_num = 'd14;
	end
	else if (delay_cnt > 'd15000 && delay_cnt <= 'd16000) begin
		delay_num = 'd15;
	end
	else begin
		delay_num = 'd0;
	end
end

//状态机第三段,结果输出,组合逻辑
assign  count     =  (state == CNT)?(delay - delay_num):'d0;
assign  counting  =  (state == CNT);
assign  done      =  (state == WAIT);

endmodule

fsm onehot

假设使用以下单热编码,则通过检查派生下一状态逻辑方程和输出逻辑方程:(S,S1,S11,S110,B0,B1,B2,B3,计数,等待)= (10'b0000000001,10'b00000000010,10'b00000000100,...,10'b10000000000)

module top_module(
    input           d,
    input           done_counting,
    input           ack,
    input  [9:0]    state,    // 10-bit one-hot current state
    output          B3_next,
    output          S_next,
    output          S1_next,
    output          Count_next,
    output          Wait_next,
    output          done,
    output          counting,
    output          shift_ena
);

parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;

assign B3_next = (state[B2]);
assign S_next = (state[S] && ~d) | (state[S1] && ~d) | (state[S110] && ~d) | (state[Wait] && ack);
assign S1_next = (state[S] && d);
assign Count_next = (state[B3] | (state[Count] && ~done_counting));
assign Wait_next = (state[Count] && done_counting) | (state[Wait] && ~ack);
assign done = state[Wait];
assign counting = state[Count];
assign shift_ena = (state[B0] | state[B1] | state[B2] | state[B3]);

endmodule
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【HDLBits 刷题 13】Buliding Larger Circuits 的相关文章

  • 如何在 Verilog 中定义带参数的模块?

    我想定义一个add有一个参数的模块 但我对新实例的声明进展不顺利 我想定义这个模块的一个实例 module add parameter wd 1 input wire wd 1 0 a b output wire wd 1 0 o assi
  • 如何使用 Verilog 宏模拟 $display?

    我想创建一个具有多个参数的宏 就像 display 一样 我的代码看起来像这样 但它不起作用 define format macro A write s sformatf A 这就是我调用 format macro 的方式 format m
  • 使用数据流模型的T触发器

    我正在尝试模拟 t flipflop 的工作 timescale 1ns 1ps module t flipflop input t input clk input clear output q output qbar wire sbar
  • Verilog 中总是后面跟着 #(...) pound 是什么意思?

    在一个简单的时钟生成器示例中 我看到以下代码 always cycle 2 clk clk 我以前总是见过 但没见过井号 我试图在文档中找到它 但我所能找到的只是一些对 实值端口 的引用 没有进一步的阐述 这是一个延迟操作 它本质上只是读取
  • 用于 Verilog 或 SystemVerilog 的 TAP(测试任何协议)模块

    是否有 TAP 测试任何协议 http testanything org Verilog 的实现 那就太好了 因为这样我就可以使用证明来自动检查我的结果 更新 10 9 09 有人问为什么不使用断言 部分 TAP 为我提供了一些很好的报告
  • 修改后的 baugh-wooley 算法乘法 verilog 代码不能正确乘法

    以下 verilog 源代码和 或测试平台可以很好地工作商业模拟器 iverilog https www edaplayground com x 3TuQ也形式化验证工具 yosys smtbmc https gist github com
  • Matlab图像处理系列——图像复原之噪声模型仿真

    微信公众号上线 搜索公众号 小灰灰的FPGA 关注可获取相关源码 定期更新有关FPGA的项目以及开源项目源码 包括但不限于各类检测芯片驱动 低速接口驱动 高速接口驱动 数据信号处理 图像处理以及AXI总线等 本节目录 一 图像复原的模型 二
  • Vivado ILA的debug信息保存与读取

    保存 write hw ila data D Project FPGA ILA Debug Data 202401041115 ila upload hw ila data hw ila 1 读取 display hw ila data r
  • 「HDLBits题解」Gates4

    本专栏的目的是分享可以通过HDLBits仿真的Verilog代码 以提供参考 各位可同时参考我的代码和官方题解代码 或许会有所收益 题目链接 Gates4 HDLBits module top module input 3 0 in out
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573
  • ESP10B 锁定连接器

    ESP10B 锁定连接器 ESP10B 电机新增内容包括双极型号标准 NEMA 尺寸 17 23 和 34 的步进电机现在包括输出扭矩范围从 61 盎司英寸到 1291 盎司英寸的双极型号 该电机配有带锁定连接器的尾缆 可轻松连接 每转可步
  • 在verilog中将wire值转换为整数

    我想将电线中的数据转换为整数 例如 wire 2 0 w 3 b101 我想要一个将其转换为 5 并将其存储在整数中的方法 我怎样才能以比这更好的方式做到这一点 j 1 for i 0 i lt 2 i i 1 begin a a w i
  • if 语句导致 Verilog 中的锁存推断?

    我正在编写用于合成算法的 Verilog 代码 我对哪些情况可能导致推断锁存器有点困惑 下面是这样的一段代码 虽然它在模拟中工作得很好 但我担心它可能会导致硬件问题 always b1 or b2 b1 map b2 map m1 map
  • Verilog 中的“net”代表什么?

    我刚刚开始学习Verilog 据我了解 Verilog有net数据类型 什么是net代表 网络就是这样一种数据类型 您不使用它来存储值 它们代表物理连接 您可以将线路视为一种网络数据类型 你可以去网上看看更多here http www ee
  • verilog $readmemh 对于 50x50 像素 RGB 图像花费太多时间

    我正在尝试编译用于 FPGA 编程的 verilog 代码 我将在其中实现 VGA 应用程序 我使用 QuartusII 和 Altera 我正在尝试正确使用 readmemh 来逐像素获取图片 现在 我已经使用 matlab 将图片转换为
  • 始终块中的 Veriloggenerate/genvar

    我试图让一个模块通过 ISE 12 4 中的语法检查 但它给了我一个我不明白的错误 首先是代码片段 parameter ROWBITS 4 reg ROWBITS 1 0 temp genvar c generate always pose
  • 在 Verilog 程序中使用连续分配?

    在 Verilog 程序中使用连续赋值是否可能和 或有用 例如 是否有任何理由将assign里面一个always堵塞 例如这段代码 always begin assign data in Data end 此外 是否可以用这种方法生成顺序逻
  • VIM 高亮匹配开始/结束

    我正在尝试找到一个插件 它将突出显示与 Verilog 匹配的开始 结束语句 VIM 可以使用花括号 方括号 但不能使用它的开始 结束 我希望 VIM 突出显示正确的开始到正确的结束 在我看来 最好的选择是使用 matchit 该脚本是 v
  • Verilog 按位或 ("|") 单子

    我见过 Verilog 代码 其中使用了按位或运算符 目的是什么 例如 address 15 14 0 or address 15 14 io din ramrd 不能省略 吗在这些情况下 在这种情况下 它充当归约运算符 例如 4 b100
  • 具有内部赋值延迟的阻塞和非阻塞语句之间的区别

    以下 2 个 verilog 代码片段有什么区别 1 always in out 5 in AND 2 always in out lt 5 in 考虑到always块中不存在其他行 输出会有什么不同吗 问题参考幻灯片 16 参见 o5 和

随机推荐