【问题标题】:Verilog code runs in simulation as i predicted but does not in FPGAVerilog 代码如我预测的那样在模拟中运行,但在 FPGA 中没有
【发布时间】:2014-06-30 12:54:23
【问题描述】:

我尝试编写一个 UART 发送器模块。它从 data[7:0] 获取数据,然后通过 Tx 串行发送。我编写了一个名为 Tester 的模块来测试发射机。它像我预测的那样在 Isim 中进行模拟,但在 Spartan-6 中没有。我用示波器观察了 Tx 引脚,我只看到逻辑 1。我无法检测到问题。我做错了什么?

module Tester(
clk,
data,
oclk,
Tx
);
input wire clk;
output reg [7:0] data;
output wire oclk;
output wire Tx;

assign oclk = clk;

initial begin
data<=8'b11001010;
end

UartTransmitter UT(.clk(clk),.data(8'b11001010),.Tx(Tx),.transmit(1'b1)); 

endmodule


module UartTransmitter(
//Inputs
clk,
reset,
data,
transmit,
//Output
Tx
);
input wire clk;
input wire reset;
input wire [7:0] data;
input wire transmit;
output reg Tx;

reg [16:0] counter;
reg durum;
reg s_durum;
reg sendbyone;
reg [10:0]buffer;
reg [3:0]nbitstransmitted;

parameter IDLE = 1'b0;
parameter TRANSMITTING = 1'b1;

initial begin
    counter=0;
    Tx=1;
    s_durum = IDLE;
    durum=IDLE;
    sendbyone=0;
    buffer=0;
    nbitstransmitted=0;
end

always @(posedge clk) begin
    counter<=counter+1;
    if(counter>=13019) begin
        counter<=0;
        sendbyone<=1;
    end else begin
        sendbyone<=0;
    end
    durum<=s_durum;
end


always @(*) begin
    s_durum=durum;
    if((durum==IDLE) && (transmit==1)) begin
    buffer={1'b1,^data,data,1'b0};
    s_durum=TRANSMITTING;
    end

    else if(durum==TRANSMITTING && (sendbyone==1)) begin
        if(nbitstransmitted<10) begin
            Tx=buffer[nbitstransmitted];
            nbitstransmitted=nbitstransmitted+1;
        end else if(nbitstransmitted==10)begin
            Tx=buffer[10];
            nbitstransmitted=0;
            s_durum=IDLE;
        end
    end
end

endmodule

【问题讨论】:

  • 您是否测试过您能够实际修改 Tx 引脚,即使是静态的?如果您只是根据开关将其驱动到 0 或 1,您会看到它切换吗?我会先测试一下。
  • Txnbitstransmitted 是推断的锁存器。根据合成器和时序,TRANSMITTING 状态可能存在反馈循环。尝试将nbitstransmitted 制作成触发器,因为这是反馈所在。如果Tx 也是一个触发器,我更愿意,但它是一个简单的触发器,所以它不需要。

标签: verilog fpga xilinx hdl synthesis


【解决方案1】:

bufferTxnbitstransmitted 是推断的锁存器。当组合块中的变量不能保证赋值时,会推断出锁存器 (always @*)。 buffer 是一个简单的锁存器,因为控制逻辑来自触发器。 Tx 将在nbitstransmitted 更改为触发器后成为简单的锁存器。主要问题是nbitstransmitted,因为它有反馈。对于当前的仿真设计,如果datadurum==TRANSMITTING &amp;&amp; sendbyone 时发生变化,那么nbitstransmitted 将递增。即使data 来自同一时钟域中的触发器,在 FPGA 上,每个位都可能存在偏差并触发多次更新。

复杂的闩锁容易出现竞争条件并占用大量区域。例如,我将提供代码复制到EDAplayground 并与 Yosys 0.3.0 合成。启用“显示图”后,它将显示大量使用的具有足够锁存反馈的门。尝试运行 here (抱歉我无法上传图表,也许其他人可以)

按照durum 已经使用的相同策略,解决方案很简单;创建下一个状态变量。坚持当前的约定,为bufferTxnbitstransmitted 创建新变量,并使用带有s_ 前缀的受人尊敬的名称。组合块 (always @*) 将分配 s_ 信号,并应默认为相应的对应部分。并且顺序块 (always @(posedge clk)) 将由他们尊敬的s_ 分配触发器。触发器消除了异步反馈并简化了设计。为了更简洁的设计,我将counter&lt;=counter+1; 移动到else 条件中并注释掉if(nbitstransmitted==10)。尝试运行 here


与问题无关的其他说明:

reset 信号未被使用。我建议在顺序块中使用它并删除initial 块。大多数 FPGA 支持initial,而大多数 ASIC 不支持。我更喜欢在初始块上使用重置信号,因为它允许重置设备而无需重启。只是一个建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 2019-12-12
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多