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

Subversion Repositories warp

[/] [warp/] [rtl/] [tmu_edgetrace.v] - Rev 7

Compare with Previous | Blame | View Log

/*
 * Milkymist VJ SoC
 * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
 *
 * This program is free and excepted software; you can use it, redistribute it
 * and/or modify it under the terms of the Exception General Public License as
 * published by the Exception License Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the Exception General Public License for more
 * details.
 *
 * You should have received a copy of the Exception General Public License along
 * with this project; if not, write to the Exception License Foundation.
 */
 
module tmu_edgetrace(
	input sys_clk,
	input sys_rst,
 
	output reg busy,
 
	input pipe_stb_i,
	output reg pipe_ack_o,
	input [10:0] A_S_X,
	input [10:0] A_S_Y,
	input [10:0] A_D_X,
	input [10:0] A_D_Y,
	input [10:0] B_D_Y,
	input [10:0] C_D_Y,
 
	input dx1_positive,
	input [10:0] dx1_q,
	input [10:0] dx1_r,
	input dx2_positive,
	input [10:0] dx2_q,
	input [10:0] dx2_r,
	input dx3_positive,
	input [10:0] dx3_q,
	input [10:0] dx3_r,
 
	input du1_positive,
	input [10:0] du1_q,
	input [10:0] du1_r,
	input du2_positive,
	input [10:0] du2_q,
	input [10:0] du2_r,
	input du3_positive,
	input [10:0] du3_q,
	input [10:0] du3_r,
 
	input dv1_positive,
	input [10:0] dv1_q,
	input [10:0] dv1_r,
	input dv2_positive,
	input [10:0] dv2_q,
	input [10:0] dv2_r,
	input dv3_positive,
	input [10:0] dv3_q,
	input [10:0] dv3_r,
 
	input [10:0] divisor1,
	input [10:0] divisor2,
	input [10:0] divisor3,
 
	output reg pipe_stb_o,
	input pipe_ack_i,
	output reg [10:0] Y,   /* common Y coordinate */
	output reg [10:0] S_X, /* start point */
	output reg [10:0] S_U,
	output reg [10:0] S_V,
	output reg [10:0] E_X, /* end point */
	output reg [10:0] E_U,
	output reg [10:0] E_V
);
 
reg load;
 
/* Register some inputs */
reg [10:0] B_D_Y_r;
reg [10:0] C_D_Y_r;
 
reg dx1_positive_r;
reg [10:0] dx1_q_r;
reg [10:0] dx1_r_r;
reg dx2_positive_r;
reg [10:0] dx2_q_r;
reg [10:0] dx2_r_r;
reg dx3_positive_r;
reg [10:0] dx3_q_r;
reg [10:0] dx3_r_r;
reg du1_positive_r;
reg [10:0] du1_q_r;
reg [10:0] du1_r_r;
reg du2_positive_r;
reg [10:0] du2_q_r;
reg [10:0] du2_r_r;
reg du3_positive_r;
reg [10:0] du3_q_r;
reg [10:0] du3_r_r;
reg dv1_positive_r;
reg [10:0] dv1_q_r;
reg [10:0] dv1_r_r;
reg dv2_positive_r;
reg [10:0] dv2_q_r;
reg [10:0] dv2_r_r;
reg dv3_positive_r;
reg [10:0] dv3_q_r;
reg [10:0] dv3_r_r;
reg [10:0] divisor1_r;
reg [10:0] divisor2_r;
reg [10:0] divisor3_r;
always @(posedge sys_clk) begin
	if(load) begin
		B_D_Y_r <= B_D_Y;
		C_D_Y_r <= C_D_Y;
		dx1_positive_r <= dx1_positive;
		dx1_q_r <= dx1_q;
		dx1_r_r <= dx1_r;
		dx2_positive_r <= dx2_positive;
		dx2_q_r <= dx2_q;
		dx2_r_r <= dx2_r;
		dx3_positive_r <= dx3_positive;
		dx3_q_r <= dx3_q;
		dx3_r_r <= dx3_r;
		du1_positive_r <= du1_positive;
		du1_q_r <= du1_q;
		du1_r_r <= du1_r;
		du2_positive_r <= du2_positive;
		du2_q_r <= du2_q;
		du2_r_r <= du2_r;
		du3_positive_r <= du3_positive;
		du3_q_r <= du3_q;
		du3_r_r <= du3_r;
		dv1_positive_r <= dv1_positive;
		dv1_q_r <= dv1_q;
		dv1_r_r <= dv1_r;
		dv2_positive_r <= dv2_positive;
		dv2_q_r <= dv2_q;
		dv2_r_r <= dv2_r;
		dv3_positive_r <= dv3_positive;
		dv3_q_r <= dv3_q;
		dv3_r_r <= dv3_r;
		divisor1_r <= divisor1;
		divisor2_r <= divisor2;
		divisor3_r <= divisor3;
	end
end
 
/* Current points, with X's unordered */
reg [10:0] I_X;
reg [10:0] I_U;
reg [10:0] I_V;
reg [10:0] J_X;
reg [10:0] J_U;
reg [10:0] J_V;
 
/* Sort the points according to X's */
always @(posedge sys_clk) begin
	if(I_X < J_X) begin
		S_X <= I_X;
		S_U <= I_U;
		S_V <= I_V;
		E_X <= J_X;
		E_U <= J_U;
		E_V <= J_V;
	end else begin
		S_X <= J_X;
		S_U <= J_U;
		S_V <= J_V;
		E_X <= I_X;
		E_U <= I_U;
		E_V <= I_V;
	end
end
 
/* See scantrace.v for a simpler version of the interpolation algorithm.
 * Here, we only repeat it.
 */
 
/* Current point datapath */
/* control signals: */
reg addDX1; /* add DX1 to J */
reg addDX2; /* add DX2 to I */
reg addDX3; /* add DX3 to J */
 
/* error accumulators: */
reg [11:0] errIX2;
reg [11:0] errIU2;
reg [11:0] errIV2;
reg [11:0] errJX1;
reg [11:0] errJU1;
reg [11:0] errJV1;
reg [11:0] errJX3;
reg [11:0] errJU3;
reg [11:0] errJV3;
 
/* intermediate variables: */
reg correctJX1;
reg correctJU1;
reg correctJV1;
reg correctJX3;
reg correctJU3;
reg correctJV3;
 
reg correctIX2;
reg correctIU2;
reg correctIV2;
 
always @(posedge sys_clk) begin
	if(load) begin
		I_X = A_D_X;
		I_U = A_S_X;
		I_V = A_S_Y;
		J_X = A_D_X;
		J_U = A_S_X;
		J_V = A_S_Y;
 
		errIX2 = 12'd0;
		errIU2 = 12'd0;
		errIV2 = 12'd0;
		errJX1 = 12'd0;
		errJU1 = 12'd0;
		errJV1 = 12'd0;
		errJX3 = 12'd0;
		errJU3 = 12'd0;
		errJV3 = 12'd0;
	end else begin
		/* J */
		if(addDX1) begin
			errJX1 = errJX1 + dx1_r_r;
			correctJX1 = (errJX1[10:0] > {1'b0, divisor1_r[10:1]}) & ~errJX1[11];
			if(dx1_positive_r) begin
				J_X = J_X + dx1_q_r;
				if(correctJX1)
					J_X = J_X + 11'd1;
			end else begin
				J_X = J_X - dx1_q_r;
				if(correctJX1)
					J_X = J_X - 11'd1;
			end
			if(correctJX1)
				errJX1 = errJX1 - {1'b0, divisor1_r};
 
			errJU1 = errJU1 + du1_r_r;
			correctJU1 = (errJU1[10:0] > {1'b0, divisor1_r[10:1]}) & ~errJU1[11];
			if(du1_positive_r) begin
				J_U = J_U + du1_q_r;
				if(correctJU1)
					J_U = J_U + 11'd1;
			end else begin
				J_U = J_U - du1_q_r;
				if(correctJU1)
					J_U = J_U - 11'd1;
			end
			if(correctJU1)
				errJU1 = errJU1 - {1'b0, divisor1_r};
 
			errJV1 = errJV1 + dv1_r_r;
			correctJV1 = (errJV1[10:0] > {1'b0, divisor1_r[10:1]}) & ~errJV1[11];
			if(dv1_positive_r) begin
				J_V = J_V + dv1_q_r;
				if(correctJV1)
					J_V = J_V + 11'd1;
			end else begin
				J_V = J_V - dv1_q_r;
				if(correctJV1)
					J_V = J_V - 11'd1;
			end
			if(correctJV1)
				errJV1 = errJV1 - {1'b0, divisor1_r};
		end else if(addDX3) begin
			errJX3 = errJX3 + dx3_r_r;
			correctJX3 = (errJX3[10:0] > {1'b0, divisor3_r[10:1]}) & ~errJX3[11];
			if(dx3_positive_r) begin
				J_X = J_X + dx3_q_r;
				if(correctJX3)
					J_X = J_X + 11'd1;
			end else begin
				J_X = J_X - dx3_q_r;
				if(correctJX3)
					J_X = J_X - 11'd1;
			end
			if(correctJX3)
				errJX3 = errJX3 - {1'b0, divisor3_r};
 
			errJU3 = errJU3 + du3_r_r;
			correctJU3 = (errJU3[10:0] > {1'b0, divisor3_r[10:1]}) & ~errJU3[11];
			if(du3_positive_r) begin
				J_U = J_U + du3_q_r;
				if(correctJU3)
					J_U = J_U + 11'd1;
			end else begin
				J_U = J_U - du3_q_r;
				if(correctJU3)
					J_U = J_U - 11'd1;
			end
			if(correctJU3)
				errJU3 = errJU3 - {1'b0, divisor3_r};
 
			errJV3 = errJV3 + dv3_r_r;
			correctJV3 = (errJV3[10:0] > {1'b0, divisor3_r[10:1]}) & ~errJV3[11];
			if(dv3_positive_r) begin
				J_V = J_V + dv3_q_r;
				if(correctJV3)
					J_V = J_V + 11'd1;
			end else begin
				J_V = J_V - dv3_q_r;
				if(correctJV3)
					J_V = J_V - 11'd1;
			end
			if(correctJV3)
				errJV3 = errJV3 - {1'b0, divisor3_r};
		end
		/* I */
		if(addDX2) begin
			errIX2 = errIX2 + dx2_r_r;
			correctIX2 = (errIX2[10:0] > {1'b0, divisor2_r[10:1]}) & ~errIX2[11];
			if(dx2_positive_r) begin
				I_X = I_X + dx2_q_r;
				if(correctIX2)
					I_X = I_X + 11'd1;
			end else begin
				I_X = I_X - dx2_q_r;
				if(correctIX2)
					I_X = I_X - 11'd1;
			end
			if(correctIX2)
				errIX2 = errIX2 - {1'b0, divisor2_r};
 
			errIU2 = errIU2 + du2_r_r;
			correctIU2 = (errIU2[10:0] > {1'b0, divisor2_r[10:1]}) & ~errIU2[11];
			if(du2_positive_r) begin
				I_U = I_U + du2_q_r;
				if(correctIU2)
					I_U = I_U + 11'd1;
			end else begin
				I_U = I_U - du2_q_r;
				if(correctIU2)
					I_U = I_U - 11'd1;
			end
			if(correctIU2)
				errIU2 = errIU2 - {1'b0, divisor2_r};
 
			errIV2 = errIV2 + dv2_r_r;
			correctIV2 = (errIV2[10:0] > {1'b0, divisor2_r[10:1]}) & ~errIV2[11];
			if(dv2_positive_r) begin
				I_V = I_V + dv2_q_r;
				if(correctIV2)
					I_V = I_V + 11'd1;
			end else begin
				I_V = I_V - dv2_q_r;
				if(correctIV2)
					I_V = I_V - 11'd1;
			end
			if(correctIV2)
				errIV2 = errIV2 - {1'b0, divisor2_r};
		end
	end
end
 
/* Y datapath */
reg incY;
always @(posedge sys_clk) begin
	if(load)
		Y <= A_D_Y;
	else if(incY)
		Y <= Y + 11'd1;
end
 
wire reachedB = (Y == B_D_Y_r);
wire reachedC = (Y == C_D_Y_r);
 
/* FSM-based controller */
 
reg [2:0] state;
reg [2:0] next_state;
 
parameter IDLE			= 3'd0;
parameter A_NEXT		= 3'd1;
parameter A_PIPEOUT_WAIT	= 3'd2;
parameter A_PIPEOUT		= 3'd3;
parameter B_START		= 3'd4;
parameter B_NEXT		= 3'd5;
parameter B_PIPEOUT_WAIT	= 3'd6;
parameter B_PIPEOUT		= 3'd7;
 
/* Register to handle the "AB horizontal" corner case properly */
reg ABh;
reg next_ABh;
 
always @(posedge sys_clk)
	ABh <= next_ABh;
 
always @(posedge sys_clk) begin
	if(sys_rst)
		state <= IDLE;
	else
		state <= next_state;
end
 
always @(*) begin
	next_state = state;
 
	busy = 1'b1;
 
	pipe_ack_o = 1'b0;
	pipe_stb_o = 1'b0;
 
	load = 1'b0;
 
	addDX1 = 1'b0;
	addDX2 = 1'b0;
	addDX3 = 1'b0;
 
	incY = 1'b0;
 
	next_ABh = ABh;
 
	case(state)
		IDLE: begin
			busy = 1'b0;
			pipe_ack_o = 1'b1;
			next_ABh = 1'b1;
			if(pipe_stb_i) begin
				load = 1'b1;
				next_state = A_PIPEOUT_WAIT;
			end
		end
		/* We start the triangle by using factors 2 and 1 */
		A_NEXT: begin
			addDX1 = 1'b1;
			addDX2 = 1'b1;
			next_ABh = 1'b0;
			next_state = A_PIPEOUT_WAIT;
		end
		/* There is one cycle latency because the point must be sorted by X's
		 * (see the beginning of this file).
		 */
		A_PIPEOUT_WAIT: next_state = A_PIPEOUT;
		A_PIPEOUT: begin
			if(reachedB & ABh) begin
				/* We reach B right from the beginning: AB is horizontal.
				 * In this case, the D1 factors have been set so that J becomes B
				 * in one step (we must enter state B_START with J=B).
				 */
				addDX1 = 1'b1;
				next_state = B_START;
			end else begin
				pipe_stb_o = 1'b1;
				if(pipe_ack_i) begin
					if(reachedB)
						next_state = B_START;
					else begin
						incY = 1'b1;
						next_state = A_NEXT;
					end
				end
			end
		end
 
		/* Once we reach B, we use factors 2 and 3 */
		B_START: begin
			if(reachedC)
				next_state = IDLE;
			else
				next_state = B_PIPEOUT_WAIT;
		end
		B_NEXT: begin
			addDX3 = 1'b1;
			addDX2 = 1'b1;
			next_state = B_PIPEOUT_WAIT;
		end
		B_PIPEOUT_WAIT: next_state = B_PIPEOUT;
		B_PIPEOUT: begin
			pipe_stb_o = 1'b1;
			if(pipe_ack_i) begin
				if(reachedC)
					next_state = IDLE;
				else begin
					incY = 1'b1;
					next_state = B_NEXT;
				end
			end
		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.