4位数据1时钟周期并行移位Verilog实现正确性及FPGA可合成性问询
问题描述
需求:实现4位数据序列依次写入寄存器A、B、C,每级寄存器相对前一级延迟1个时钟周期。
以下是实现的Verilog设计代码:
module shift4bit(clock, data, out, outRegA, outRegB, outRegC); input clock; input [3:0] data; output [3:0] out; output [3:0] outRegA; output [3:0] outRegB; output [3:0] outRegC; reg [3:0] RegA; reg [3:0] RegB; reg [3:0] RegC; always @(posedge clock) begin RegA <= data; RegB <= RegA; RegC <= RegB; end assign out = data; assign outRegA = RegA; assign outRegB = RegB; assign outRegC = RegC; endmodule
对应的测试平台代码:
`timescale 1ns / 1ps module shift4bit_tb; // Inputs reg [3:0] data; reg clock; // Outputs wire [3:0] out; wire [3:0] outRegA; wire [3:0] outRegB; wire [3:0] outRegC; // Instantiate the Unit Under Test (UUT) shift4bit uut (.clock(clock),.data(data),.out(out),.outRegA(outRegA),.outRegB(outRegB),.outRegC(outRegC)); initial begin // Initialize Inputs data = 4'b1111; clock = 1'b1; // Wait 100 ns for global reset to finish #20; // Add stimulus here data = 4'b0001; #20; data = 4'b0010; #20; data = 4'b0011; #20; data = 4'b0100; #20; data = 4'b0101; #20; data = 4'b0110; #20; data = 4'b0111; #20; data = 4'b1000; #20; end always #10 clock = ~clock; endmodule
已得到仿真结果,显示存在预期的移位效果,现咨询:该代码逻辑是否正确?能否在FPGA上合成实现?
代码分析与结论
1. 逻辑正确性
代码完全符合需求:
- 采用**非阻塞赋值
<=**在时钟上升沿同步更新寄存器,保证每级寄存器的时序延迟:- 每个时钟上升沿,
RegA捕获当前data的值;RegB捕获上一个时钟周期RegA的值;RegC捕获上一个时钟周期RegB的值。 - 最终实现
data → RegA(延迟1周期)→ RegB(延迟2周期)→ RegC(延迟3周期)的移位效果,和需求完全匹配。
- 每个时钟上升沿,
- 测试平台的时钟周期为20ns(每10ns翻转一次),
data每20ns更新一次,刚好与时钟沿对齐,仿真结果能正确验证移位逻辑。
2. FPGA可合成性
该代码可以直接在FPGA上合成实现:
- 代码使用的是FPGA工具完全支持的标准同步时序电路语法:
always @(posedge clock)描述的寄存器、assign描述的组合逻辑,均属于可综合语法范畴。 - 这种链式寄存器结构会被FPGA综合工具直接映射到器件内部的触发器资源,不存在合成障碍。
3. 工程优化建议(可选)
当前代码未包含复位逻辑,虽然不影响功能正确性,但在实际FPGA工程中,建议添加同步复位端口,用于初始化寄存器状态,避免上电后寄存器处于未知状态:
// 修改模块端口,添加复位信号 module shift4bit(clock, reset, data, out, outRegA, outRegB, outRegC); input clock; input reset; // 新增同步复位端口,高电平有效 input [3:0] data; output [3:0] out; output [3:0] outRegA; output [3:0] outRegB; output [3:0] outRegC; reg [3:0] RegA; reg [3:0] RegB; reg [3:0] RegC; always @(posedge clock) begin if(reset) begin RegA <= 4'b0000; RegB <= 4'b0000; RegC <= 4'b0000; end else begin RegA <= data; RegB <= RegA; RegC <= RegB; end end // 其余assign语句不变 assign out = data; assign outRegA = RegA; assign outRegB = RegB; assign outRegC = RegC; endmodule
内容的提问来源于stack exchange,提问作者Andy Ayr
相关产品推荐
相关产品推荐

