OpenCores
URL https://opencores.org/ocsvn/a429_transmitter_receiver/a429_transmitter_receiver/trunk

Subversion Repositories a429_transmitter_receiver

[/] [a429_transmitter_receiver/] [trunk/] [rtl/] [a429_rx_iface.v] - Rev 2

Compare with Previous | Blame | View Log

 
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2019 Himar Alonso
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this hardware, software, and associated documentation files
// (the "Product"), to deal in the Product without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Product, and to permit
// persons to whom the Product is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Product.
//
// THE PRODUCT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE PRODUCT OR THE USE OR OTHER DEALINGS IN THE
// PRODUCT. 
//
////////////////////////////////////////////////////////////////////////////////
// A429 Receiving Interface
// 
// Designed by Himar Alonso (himar@opencores.org)
// Date: 15/08/2019
////////////////////////////////////////////////////////////////////////////////
 
module a429_rx_iface
(
	input             clk2M,
	input             reset,
	input             enable,
	input       [1:0] speed,
	input             a429_in_a,
	input             a429_in_b,
	input             parcheck,
	output reg [32:1] data,
	output reg        wr_en
);
 
	////////////////////////////////////////
	// Constants for the sampling counter //
	////////////////////////////////////////
	// Counter values for first/other sampling intervals
	// 2.5us/10us for 100Kbps mode,
	// 20us/80us for 12,5Kbps mode.
	wire [8:0] first_sc_value = (speed[0]) ? 9'd4  : 9'd39;
	wire [8:0] other_sc_value = (speed[0]) ? 9'd19 : 9'd159;
 
	// Counter values for gap search
	// 40us for 100Kbps mode, setting it to 30us
	// 320us for 12,5Kbps mode, setting it to 240us.
	wire [8:0] gap_sc_value = (speed[0]) ? 9'd59 : 9'd479;
 
	///////////////////////////////////////////////////////
	// Register 'aorb' previous value for edge detection //
	///////////////////////////////////////////////////////
	wire aandb = a429_in_a & a429_in_b;
	wire aorb = a429_in_a | a429_in_b;
	reg  aorb_prev;
 
	always @(posedge clk2M or posedge reset)
		if (reset)
			aorb_prev <= 1'b0;
		else
			aorb_prev <= aorb;
 
	///////////////////////////////////////////////
	// RX state machine parameters and registers //
	///////////////////////////////////////////////
	localparam IDLE       = 2'b00;
	localparam RECEIVING  = 2'b01;
	localparam WAITFORGAP =	2'b10;
 
	reg   [1:0] state;
	reg         parity;
	reg  [32:1] shift_reg;
	reg   [4:0] shift_counter;
	reg   [8:0] sampling_counter;
 
	/////////////////////////////////////
	// RX state machine implementation //
	/////////////////////////////////////
	always @(posedge clk2M or posedge reset)
		if (reset) begin
			state <= WAITFORGAP;
			sampling_counter <= gap_sc_value;
			shift_counter <= 5'b0;
			data <= 32'b0;
			shift_reg <= 32'b0;
			wr_en <= 1'b0;
		end else begin
			case (state)
				IDLE:
					//
					// Wait for 'aorb' rising edge
					//
					begin
						parity <= 1'b0;
						sampling_counter <= first_sc_value;
						shift_counter <= 5'd31;
						if (aorb & !aorb_prev)
							state <= RECEIVING;
					end
				RECEIVING:
					//
					// Logical shift right until shift_counter = 0
					//
					if (~|sampling_counter)
						if ((aandb == 1'b1) || (aorb == 1'b0)) begin // Bus error
							sampling_counter <= gap_sc_value;
							state <= WAITFORGAP;
						end else if (~|shift_counter) begin // Complete word received
							data <= {a429_in_a, shift_reg[32:10],
								shift_reg[2], shift_reg[3], shift_reg[4], shift_reg[5],
								shift_reg[6], shift_reg[7], shift_reg[8], shift_reg[9]};
							if ((parity == a429_in_b) || !parcheck) // Odd parity ok, or no parity check
								wr_en <= 1'b1;
							sampling_counter <= gap_sc_value;
							state <= WAITFORGAP;
						end else begin // bit received
							shift_reg <= {a429_in_a, shift_reg[32:2]};
							parity <= parity ^ a429_in_a;
							shift_counter <= shift_counter - 5'b1;
							sampling_counter <= other_sc_value;
						end
					else
						sampling_counter <= sampling_counter - 9'b1;
				WAITFORGAP:
					//
					// Wait until a new gap is found
					//
					begin
						wr_en <= 1'b0;
						if (~|sampling_counter)
							state <= IDLE;
						else if (aorb == 1'b1)
							sampling_counter <= gap_sc_value;
						else
							sampling_counter <= sampling_counter - 9'b1;
					end
				default: // This should never happen
					begin
						wr_en <= 1'b0;
						sampling_counter <= gap_sc_value;
						state <= WAITFORGAP;
					end
			endcase
		end
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.