-1
\$\begingroup\$

I am new to FPGAs and I'm trying to make a UART receiver in a Spartan 6 xc6slx9 FPGA. I searched online about UART receivers but almost all of them use FSMs. I don't yet know about FSMs. I have written a verilog code for the receiver but it doesn't work as intended. Please tell me where I have gone wrong and how to rectify it. Thanks in advance.

////////////////////////////////////////////////////////////////////////////////////////////////////////////
module UART_RX(clk,d_in,D_Out);
input clk,d_in;//clock & Data input
output [9:0] D_Out;//Data output

reg [9:0] Clock_Divider;
always @(posedge clk)
begin
Clock_Divider <= Clock_Divider+1;
if (Clock_Divider == 54) //for 115200 baud
Clock_Divider <= 0;
end

reg Clk;
always @(Clock_Divider)
begin
if(Clock_Divider == 54)
Clk <= 1'b1;
else
Clk <= 1'b0;
end

reg latch;
always @(d_in or Rst)
begin
if(d_in == 0)
latch <= 1'b1;
if(Rst == 1)
latch <= 1'b0;
end

reg [6:0] Counter;
always @(posedge Clk)
begin
if (latch == 1)
Counter <= Counter+1;
if (Counter == 76)
Counter <= 7'b0000000;
end

reg Rst;
always @(Counter)
begin
if(Counter == 76)
Rst <= 1;
else
Rst <= 0;
end
///////////////////////////////////////////////////
reg SIPO_0;
always @(Counter)
begin
if(Counter==4)
SIPO_0 <= d_in;
end
assign D_Out[0] = SIPO_0;

reg SIPO_1;
always @(Counter)
begin
if(Counter==12)
SIPO_1 <= d_in;
end
assign D_Out[1] = SIPO_1;

reg SIPO_2;
always @(Counter)
begin
if(Counter==20)
SIPO_2 <= d_in;
end
assign D_Out[2] = SIPO_2;

reg SIPO_3;
always @(Counter)
begin
if(Counter==28)
SIPO_3 <= d_in;
end
assign D_Out[3] = SIPO_3;

reg SIPO_4;
always @(Counter)
begin
if(Counter==36)
SIPO_4 <= d_in;
end
assign D_Out[4] = SIPO_4;

reg SIPO_5;
always @(Counter)
begin
if(Counter==44)
SIPO_5 <= d_in;
end
assign D_Out[5] = SIPO_5;

reg SIPO_6;
always @(Counter)
begin
if(Counter==52)
SIPO_6 <= d_in;
end
assign D_Out[6] = SIPO_6;

reg SIPO_7;
always @(Counter)
begin
if(Counter==60)
SIPO_7 <= d_in;
end
assign D_Out[7] = SIPO_7;

reg SIPO_8;
always @(Counter)
begin
if(Counter==68)
SIPO_8 <= d_in;
end
assign D_Out[8] = SIPO_8;

reg SIPO_9;
always @(Counter)
begin
if(Counter==76)
SIPO_9 <= d_in;
end
assign D_Out[9] = SIPO_9;
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////////```
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Didn't read your code, but did you run all incoming signals that are not synchronous to your FPGA through a chain of flip-flops before using them anywhere else? This is to synchronzie them to your clock domain and remove metastability. Because if you didn't you are going to eventually have problems. \$\endgroup\$
    – DKNguyen
    Commented Mar 24, 2020 at 16:01
  • 2
    \$\begingroup\$ If you want to do HDL you can't get around FSMs so use this opportunity to learn how to make them. I read 'latch' in your code so I am not going to touch it. There is already enough misery with the corona crisis. \$\endgroup\$
    – Oldfart
    Commented Mar 24, 2020 at 16:20
  • \$\begingroup\$ I had a second look. All your always @(Counter) have incomplete sensitivity lists, missing din.Sorry, but there is just too much wrong with your code to comment upon. I urge you to have a look at existing Verilog code how a UART is done. \$\endgroup\$
    – Oldfart
    Commented Mar 24, 2020 at 16:56
  • \$\begingroup\$ See this question, and then come back and refine your question if it still hasn't been answered. \$\endgroup\$
    – Dave Tweed
    Commented Mar 24, 2020 at 19:19

1 Answer 1

-1
\$\begingroup\$

That sure is a lot of code, with no indentation and almost no comments at all. It turns out that it can be simplified to the following form, which is exactly equivalent, and a lot more readable.

module UART_RX (
  input clk,
  input d_in,
  output reg [9:0] D_Out
);

  reg [9:0] Clock_Divider;
  wire Clk = (Clock_Divider == 54); //for 115200 baud

  always @(posedge clk) begin
    Clock_Divider <= Clock_Divider + 1;
    if (Clk) Clock_Divider <= 0;
  end

  reg [6:0] Counter;
  wire Rst = (Counter == 76);

  reg latch;
  always @(d_in or Rst) begin
    if (d_in == 0) latch <= 1'b1;
    if (Rst) latch <= 1'b0;
  end

  always @(posedge Clk) begin
    if (latch) Counter <= Counter+1;
    if (Rst) Counter <= 7'b0000000;
  end

  always @(Counter) case (Counter)
     4: D_Out[0] <= d_in;
    12: D_Out[1] <= d_in;
    20: D_Out[2] <= d_in;
    28: D_Out[3] <= d_in;
    36: D_Out[4] <= d_in;
    44: D_Out[5] <= d_in;
    52: D_Out[6] <= d_in;
    60: D_Out[7] <= d_in;
    68: D_Out[8] <= d_in;
    76: D_Out[9] <= d_in;
  endcase

endmodule

Can you spot the issue described here: UART Receiver glitches? (also here: FPGA starts working after irrelevant changes, why?)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.