-1

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
////////////////////////////////////////////////////////////////////////////////////////////////////////```
eeintech
  • 946
  • 5
  • 13
  • 1
    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. – DKNguyen Mar 24 '20 at 16:01
  • 2
    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. – Oldfart Mar 24 '20 at 16:20
  • 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. – Oldfart Mar 24 '20 at 16:56
  • See [this question](https://electronics.stackexchange.com/q/137194/11683), and then come back and refine your question if it still hasn't been answered. – Dave Tweed Mar 24 '20 at 19:19

1 Answers1

-1

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?)

Dave Tweed
  • 168,369
  • 17
  • 228
  • 393