Showing posts with label FSM. Show all posts
Showing posts with label FSM. Show all posts

Wednesday, December 5, 2012

FSM Verilog project, Two FPGA transmission.

This project is to letting FPGA transmission, the final result:
reset FPGA A and B,

NOTE: about write FSM, usually we have 3 always blocks.

1. transition cur_state <= next_state, sequential, using <= statement.
2. what is the next_state? this part should be combinational, the sensitivity list should be any signal that could change the next_state, see following codes for examples. Inside this block, the code should be blocking using =.
3. what should we do in each state? this part is sequential, like a DFF device, using <=.

//---------------------Final functionality.
FPGA A set switches and push button, B's leds should lit up according to A's switches.
B set sw and push button, A's leds should lit up according to B's switches.

//-------------------data pattern:
uart_tx: 1 when idle, startBit 0, 8bit data, 1bit parity, 1bit stopbit (high)
//-----------------------transmitter.

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Wenshuai Hou
// transmitter: when the button is pressed, it reads the 8bit value from the SW, send it out serially through uart_tx, and wait for rx_done for 15cycles, if not acked, retransmit.

 module transmitter(
input clock_50M,
input reset,
input [7:0] sw,
input rx_done,
input btn,
output reg uart_tx
    );

parameter [1:0] IDLE = 0,
XMIT = 1,
ACK = 2;

reg [1:0] curr, next;
reg [3:0] count, waiting;


// this always block is always sequential, <=
always @ (posedge clock_50M or posedge reset) begin
if(reset == 1) curr <= IDLE;
else curr <= next;
end

//this one determines the next_state, should be combinational.
always @ (curr or btn or count or waiting or rx_done) begin
case(curr)
IDLE:
next = (btn == 1)? XMIT: IDLE;

XMIT:
next = (count == 0)? ACK: XMIT;

ACK: begin
if(rx_done == 1)
next = IDLE;
else if(rx_done == 0 && waiting < 15)
next = ACK;
else
next = XMIT;

end

endcase

end

// this always block determines what the FSM does in each state.
reg [10:0] tx_data;
always @ (posedge clock_50M) begin

case(curr)
IDLE:
begin
uart_tx <= 1;
count <= 10;
waiting <= 0;
tx_data <= {1'b0, sw, (^sw), 1'b1};
end

XMIT:
begin
uart_tx <= tx_data[count];
count <= count - 1;
waiting <= 0;
end

ACK:
begin
uart_tx <= 1;
waiting <= waiting + 1;
count <= 10;
end
endcase

end


endmodule



//-----------------------receiver part 

//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Wenshuai Hou 

//////////////////////////////////////////////////////////////////////////////////
module reveiver(
input clock_50M, 
input reset,
input uart_rx,  //serial input
output reg tx_done, //ack to the transmitter
output reg [7:0] leds //lit up the LEDS based on the received word.
    );
parameter [1:0] IDLE = 0,
READ = 1,
ACK = 2;
reg [1:0] curr, next;
reg [9:0] rx_data;
reg [3:0] count; 
always @ (posedge clock_50M or posedge reset) begin
if(reset == 1) curr <=  IDLE;
else curr <= next;
end
always @ (curr or uart_rx or count) begin
case(curr)
IDLE: next = (uart_rx ==0)? READ:IDLE; 
// negedge of UART_RX signify the receiving. 
READ: next = (count == 9)? ACK: READ; // to the ACK if receive complete
ACK: next = IDLE;
endcase
end
always@ (posedge clock_50M) begin
case(curr)
IDLE: begin
count <= 0 ;
tx_done <= 0 ;
end
READ: begin
rx_data[count] <= uart_rx; //save the received values.
count <= count +1;
end
ACK: begin
tx_done <= ((^rx_data[8:0]) == 0); //check for even parity. 
leds <= rx_data[7:0];
end
endcase
end

endmodule