我尝试编写UART发送器模块。它从数据[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
答案 0 :(得分:1)
buffer
,Tx
和nbitstransmitted
是推断锁存器。当无法保证变量在组合块(always @*
)中赋值时,推断出锁存器。 buffer
是一个简单的锁存器,因为控制逻辑来自触发器。在Tx
更改为触发器后,nbitstransmitted
将是简单的锁存器。主要问题是nbitstransmitted
因为它有反馈。根据模拟中的当前设计,data
时durum==TRANSMITTING && sendbyone
会发生变化,nbitstransmitted
会增加data
。即使durum
来自同一时钟域的触发器,在FPGA上也可能存在每个位的偏斜并触发多次更新。
复杂的闩锁容易出现竞争条件,占用大量区域。例如,我将提供代码复制到EDAplayground并使用Yosys 0.3.0进行综合。使用&#34;显示图表&#34;启用后,它将显示大量使用的门,并具有足够的锁存反馈。尝试运行 here (抱歉,我无法上传图表,也许其他人可以)
通过遵循已用于buffer
的相同策略,解决方案很容易;创建下一个状态变量。坚持使用当前约定,使用具有Tx
前缀的受尊重名称为nbitstransmitted
,s_
和always @*
创建新变量。组合块(s_
)将分配always @(posedge clk)
信号,并应默认为受尊重的计数器部分。顺序块(s_
)将按其受尊重的counter<=counter+1;
分配触发器。触发器删除异步反馈并简化设计。为了更清晰的设计,我将else
移到if(nbitstransmitted==10)
条件并注释掉了reset
。尝试运行 here
与该问题无关的其他说明:
未使用initial
信号。我建议在顺序块中使用它并删除initial
块。大多数FPGA支持{{1}},大多数ASIC不支持。我更喜欢在初始模块上使用复位信号,因为它允许重置设备而无需重启电源。只是一个建议。