Reputation: 13
I try to write an UART transmitter module. It gets data from data[7:0] and then sends it serially via Tx. I wrote a module named Tester for testing transmitter. It simulates in Isim as I predicted but does not in Spartan-6. I watched the Tx pin with osciloscope, I saw only logic 1. I could not detect the problem. What have I done incorrectly?
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
Upvotes: 1
Views: 394
Reputation: 19096
buffer
, Tx
and nbitstransmitted
are inferred latches. Latches are inferred when a variable is not guaranteed assignment with in an combinational block (always @*
). buffer
is a simple latch because the control logic is coming from flops. Tx
will be simple latch after nbitstransmitted
is changed to a flip-flop. The main issue is nbitstransmitted
because it has feedback. With the current design in simulation if data
changes when durum==TRANSMITTING && sendbyone
then nbitstransmitted
will increment. Even if data
is from a flop in the same clock domain, on the FPGA there can be skew on each bit and trigger multiple updates.
Complex latches are prone to race conditions and use up lots of area. As an example, I copied the provide code to EDAplayground and synthesized it with Yosys 0.3.0. With the "show diagram" enabled it will show a large number of gates used with sufficient latch feedback. Try running here (Sorry I cannot upload the diagram, maybe someone else can)
The solution is easy by following the same strategy already used for durum
; create a next state variable. sticking with the current convention, create new variables for buffer
, Tx
and nbitstransmitted
with the respected names with a s_
prefix. The combinational block (always @*
) will assign the s_
signals and should default to there respected counter part. And the sequential block (always @(posedge clk)
) will assign the flops by their respected s_
. The flops with remove the asynchronous feedback and simplify the design. For cleaner design, I moved the counter<=counter+1;
into the else
condition and commented out if(nbitstransmitted==10)
. Try running here
Other note not related to the issue:
The reset
signal is not being used. I suggest using it in the sequential block and remove the initial
block. Most FPGAs support initial
and most ASIC do not. I prefer using reset signals over initial blocks because it allows resetting the device without having to power cycle. Just a suggestion.
Upvotes: 1