Notes
This version compiles under InterHDL's Verilogger. Note that vectored nets as well as arrays of instantiations are not supported in that compiler, hence the necessity of this version. A simple little testbench has been provided as the top module.
//
// this is the structural version of the line-drawing algorithm as described
// in the proposal. note that a fsm may be grafted on top of this so that
// "mode" may be replaced by a reset which initializes the fsm to its initial
// state.
//
// fsm would look as follows:
//
// m0 --> m1 --> m2 --> m3 --+
// ^ |
// +----+
//
// with reset asserted at any time causing a cycle back to state m0.
// note that this may be encapsulated on top of the package module to
// save work and enhance modularity.
//
// m0: load x1, x2
// m1: load y1, y2
// m2: delay cycle
// m3: work cycle. continue until eoln is high.
//
// 12jan98ajb
// behavioral extension modifications 14aug99, 09sep99ajb
//
module top(eoln, xout, yout);
output eoln;
output [7:0] xout, yout;
reg [7:0] in1;
reg [7:0] in2;
reg [1:0] mode;
reg [15:0] i;
reg clk;
package p1(in1, in2, clk, eoln, mode, xout, yout);
initial
for(i=0;i<1;i=i+1)
begin
#10 mode=0; clk=0; in1=0; in2=255;
#10 clk=1;
#10 $display("xout: %d yout: %d (x-loader cycle) ",xout,yout);
#10 mode=1; clk=0; in1=0; in2=255;
#10 clk=1;
#10 $display("xout: %d yout: %d (y-loader cycle)",xout,yout);
#10 mode=2; clk=0; #10 clk=1;
#10 $display("xout: %d yout: %d (delay cycle)",xout,yout);
while(eoln==0)
begin
#10 mode=3; clk=0; #10 clk=1;
#10 $display("xout: %d yout: %d",xout,yout);
end
end
endmodule
module package(in1, in2, clk, eoln, mode, xout, yout);
input [7:0] in1;
input [7:0] in2;
input clk;
output eoln;
input [1:0] mode;
output [7:0] xout, yout;
wire [15:0] rc;
wire [15:0] rcr7,rcr8;
wire [1:0] r5out,r6out;
wire [1:0] r5bus,r6bus;
wire [7:0] x2x1,y2y1,x1out,x1r5,x2out,x1x2,y1y2;
wire [7:0] r7out,r8out,y1out,y2out,y1r6;
wire m0, m1, m2, m3, eolnbar;
assign xout=x1out;
assign yout=y1out;
//
// decode fsm position (00 01 10 11) to discrete m-control bits
//
assign m0 = mode==2'd0;
assign m1 = mode==2'd1;
assign m2 = mode==2'd2;
assign m3 = mode==2'd3;
//
// left half of diagram
//
assign x1r5 = x1out + {{7{r5bus[1]}},r5bus[0]};
assign r5bus = r5out & {2{eolnbar}};
f3 modx1(x1out, in1, x1r5, x1out, m3, m0, rc[15],clk);
f0 modx2(x2out, in2, m0,clk);
subtractor88 modx2x1(zerox2x1, x2x1, x2out, x1out,cox0),
modx1x2(zerox1x2, x1x2, x1out, x2out,cox);
killstep modr5(r5out, cox, m1, clk);
f7 modr7(r7out, x2x1, x1x2, m1, cox,clk);
//
// right half of diagram
//
assign y1r6 = y1out + {{7{r6bus[1]}},r6bus[0]};
assign r6bus = r6out & {2{eolnbar}};
f4 mody1(y1out, in1, y1r6, y1out, m3, m2, m1, rc[15],clk);
f0 mody2(y2out, in2, m1, clk);
subtractor88 mody2y1(zeroy2y1, y2y1, y2out, y1out,coy0),mody1y2(zeroy1y2, y1y2, y1out, y2out,coy);
killstep modr6(r6out, coy, m2, clk);
f7 modr8(r8out, y2y1, y1y2, m2, coy,clk);
//
// bottom part
//
assign rcr8 = rc - {8'h00, r8out};
assign rcr7 = rc + {8'h00, r7out};
f5 modrc(rc, zerox1x2 , rcr7, rcr8, m3, rc[15],clk);
//
// eoln part
//
assign eolnbar = ~eoln;
assign eoln = zerox1x2 & zeroy2y1;
endmodule
//
// subtract one eight bit number from another
// use not(co) to input of r7/r8 muxes to make unsigned comparison
//
module subtractor88(z, o, i1, i2, co);
output z,co;
output [7:0] o;
input [7:0] i1;
input [7:0] i2;
wire [1:8]zer,car;
assign z=zer[8], co=car[8];
// bsub b[1:8](car[1:8],o[0:7],i1[0:7],i2[0:7],{1'b1,car[1:7]},zer[1:8],{1'b1,zer[1:7]});
bsub b0(car[1],o[0],i1[0],i2[0],1'b1, zer[1],1'b1 );
bsub b1(car[2],o[1],i1[1],i2[1],car[1],zer[2],zer[1]);
bsub b2(car[3],o[2],i1[2],i2[2],car[2],zer[3],zer[2]);
bsub b3(car[4],o[3],i1[3],i2[3],car[3],zer[4],zer[3]);
bsub b4(car[5],o[4],i1[4],i2[4],car[4],zer[5],zer[4]);
bsub b5(car[6],o[5],i1[5],i2[5],car[5],zer[6],zer[5]);
bsub b6(car[7],o[6],i1[6],i2[6],car[6],zer[7],zer[6]);
bsub b7(car[8],o[7],i1[7],i2[7],car[7],zer[8],zer[7]);
endmodule
//
// single cell "full subtractor"
//
module bsub(co, sum, a, b, ci, zo, zi);
output co,sum,zo;
input a,b,ci,zi;
not (tb,b);
xor (t1,a,tb), (sum,t1,ci);
or (co,a&tb,tb&ci,a&ci);
not (zdet,sum);
and (zo,zi,zdet);
endmodule
//
// muxed register that accepts new input only on an m1 cycle
//
module f0(o, i, m, ck);
input [7:0] i;
input m, ck;
output [7:0] o;
reg [7:0] o;
always @(posedge ck)
if(m) o=i;
endmodule
//
// muxed register for x1 that only accepts as follows:
// m0 in1
// m3 & rc:15==0 in2
// else in3
//
module f3(o,i1,i2,i3,m3,m0,s,ck);
input [7:0] i1,i2,i3;
input m3,m0,s,ck;
output [7:0] o;
reg [7:0] o;
always @(posedge ck)
if(m0) o=i1;
else if(m3&~s) o=i2;
else o=i3;
endmodule
//
// muxed register for y1 that only accepts as follows:
// m1 in1
// m3 & rc:15 == 1 in2
// (m3 & rc:15 == 0) in3
// | (m2)
// else old y1
//
module f4(o,i1,i2,i3,m3,m2,m1,s,ck);
input [7:0] i1,i2,i3;
input m3,m2,m1,s,ck;
output [7:0] o;
reg [7:0] o;
always @(posedge ck)
if (m1) o=i1;
else if(m3)
begin
if(s) o=i2; else o=i3;
end
else if(m2) o=i3;
endmodule
//
// muxed register for rc that only accepts as following:
// m3 & rc:15 == 1 in2
// m3 & rc:15 == 0 in3
// else in1 ($0000 or $8000)
//
module f5(o,i1,i2,i3,m3,s,ck);
input i1;
input [15:0] i2,i3;
input m3,s,ck;
output [15:0] o;
reg[15:0] o;
always @(posedge ck)
if(m3)
begin
if(s) o=i2;
else o=i3;
end
else o={i1,{15{1'b0}}};
endmodule
//
// muxed register for r7 and r8 that only accepts as following:
// m & s==0 i1
// m & s==1 i2
// else previous contents
//
module f7(o, i1, i2, m, s, ck);
output [7:0]o;
reg [7:0]o;
input m,s,ck;
input [7:0] i1;
input [7:0] i2;
always @(posedge ck)
if(m)
if(s) o=i2; else o=i1;
endmodule
//
// stores either a +1 or -1 depending on whether zero out (i) is true
//
//
module killstep(o,i,m,ck);
input m, i, ck;
output [1:0] o;
wire [1:0] o;
reg w;
assign {o[0],o[1]}= {1'b1,w};
always @(posedge ck)
if(m) w=i;
endmodule