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



No comments:

Post a Comment