Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
// Author: Conor Patrick
// Description:
// top_level module for the coprocessor
// contains control logic for reading from stack memory, controlling circle
// modules, and various reads.
module plot_circle
#(
parameter DATAW=18,
parameter CIRCLES=12
)
(
input clk,
input clkfast,
input reset,
// mem mapped slave
// read
input read,
input [DATAW-1+1:0]address ,
output[31:0] readdata,
output waitrequest,
output readdatavalid,
// write
input write,
input[31:0] writedata,
// mem mapped master
// read
output mread,
output [DATAW-1:0]maddress ,
input[31:0] mreaddata,
input mwaitrequest,
input mreaddatavalid,
// write
output mwrite,
output [31:0] mwritedata
);
assign waitrequest = 1'b0;
localparam WAIT = 5'h0, READX=5'h1, READY=5'h2, READR=5'h3, BLOCK=5'h4;
reg[4:0] state,_state,lstate;
wire[7:0] rd[CIRCLES-1:0];
wire[CIRCLES-1:0] rdv;
wire[CIRCLES-1:0] ready;
reg[CIRCLES-1:0] ready_sync;
reg[7:0] rdfinal;
reg[31:0] writedatac[CIRCLES-1:0];
reg[CIRCLES-1:0] writec;
reg[CIRCLES-1:0] cselect;
reg[31:0] newdx, newdy,newdr,_mwritedata;
reg[DATAW-1:0] basex, baser, basey, _maddress;
reg signed[9:0] offset,_offset;
reg rdvfinal, _mread, _mwrite;
wire readstate;
wire readcircle;
assign readstate = (address == 19'h40000) ? 1'b1 : 1'b0;
assign writestart = ((address == 19'h40004) & write) ? 1'b1 : 1'b0;
assign readcircle = read & ~readstate;
assign readdata = readstate ? (ready == {(CIRCLES){1'b1}} ? 1'b0 : 1'b1) : (rdfinal);
assign readdatavalid = rdvfinal | readstate;
wire broadcast;
assign broadcast = (writedata[31:26] == 0) & (address[DATAW-1+1] == 1'b0);
assign mread = _mread;
assign mwrite = _mwrite;
assign maddress = _maddress;
assign mwritedata = _mwritedata;
wire writeready;
wire[31:0] writecircle;
assign writeready = (((state == WAIT || state == READY) && offset != 10'd196) ? 1'b1 : 1'b0) | (broadcast & write);
assign writecircle = (broadcast&write) ? writedata : {6'h1,newdr[7:0],newdy[8:0],newdx[8:0]};
integer i = 0;
wire clksel;
assign clksel = (state == WAIT) ? clk : clkfast;
wire[DATAW-1:0] stackaddr = writedata[DATAW-1:0];
// Read from stack memory data path
always@(posedge clk, posedge reset)
begin
if(reset)
begin
state <= WAIT;
newdx <= 0;
newdr <= 0;
newdy <= 0;
basex <= 0;
basey <= 0;
baser <= 0;
offset <= 10'd196;
lstate <= 0;
ready_sync <= 0;
end
else
begin
state <= _state;
lstate <= state;
offset <= _offset;
ready_sync <= ready;
if (writestart)
begin
basex <= stackaddr;
basey <= stackaddr + 10'd200;
baser <= stackaddr + 10'd400;
offset <= 10'd196;
state <= READX;
end
case (lstate)
WAIT:
begin
end
READX:
begin
newdx <= mreaddata;
end
READY:
begin
newdy <= mreaddata;
end
READR:
begin
newdr <= mreaddata;
end
endcase
end
end
// Read from stack memory control logic and FSM
always@*
begin
_mread = 0;
_mwrite = 0;
_mwritedata = 0;
_maddress = 0;
_state = state;
_offset = offset;
case (state)
WAIT:
begin
_offset = 10'd196;
end
READX:
begin
_state = READY;
_mread = 1'b1;
_maddress = basex + offset;
if (offset < 0)
begin
_state = WAIT;
end
end
READY:
begin
_state = READR;
_mread = 1'b1;
_maddress = basey + offset;
end
READR:
begin
if (cselect != 0)
begin
_state = READX;
_offset = offset - 4'd4;
end
else
begin
_state = BLOCK;
end
_mread = 1'b1;
_maddress = baser + offset;
end
BLOCK:
begin
if (cselect != 0)
begin
_state = READX;
_offset = offset - 4'd4;
end
end
endcase
end
// OR gate for all circles for read operations
always@*
begin
rdfinal = 1'b0;
rdvfinal = 1'b0;
for(i=0; i < CIRCLES; i=i+1)
begin
rdfinal = rd[i] | rdfinal;
rdvfinal = rdv[i] | rdvfinal;
end
end
// control logic for telling a circle module to start plotting when it is ready
// of all the cirle modules
always@*
begin
cselect = 0;
for(i=0; i < CIRCLES; i=i+1)
begin
if (ready_sync[i])
cselect = 1 << i;
end
for(i=0; i < CIRCLES; i=i+1)
begin
writec[i] = 1'b0;
writedatac[i] = 32'hx;
end
for(i=0; i < CIRCLES; i=i+1)
begin
if (cselect == (1<<i) || (broadcast && write))
begin
writec[i] = writeready;
writedatac[i] = writecircle;
end
end
end
// All of the circle modules instantiated
plot_pixel #(.ID(1),.WAITV(WAIT)) p0(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[0]),.waitrequest(),.ready(ready[0]),
.readdatavalid(rdv[0]), .broadcast(broadcast & write),
.write(writec[0]),.writedata(writedatac[0]));
plot_pixel #(.ID(2),.WAITV(WAIT)) p1(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[1]),.waitrequest(),.ready(ready[1]),
.readdatavalid(rdv[1]), .broadcast(broadcast & write),
.write(writec[1]),.writedata(writedatac[1]));
plot_pixel #(.ID(3),.WAITV(WAIT)) p2(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[2]),.waitrequest(),.ready(ready[2]),
.readdatavalid(rdv[2]), .broadcast(broadcast & write),
.write(writec[2]),.writedata(writedatac[2]));
plot_pixel #(.ID(4),.WAITV(WAIT)) p3(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[3]),.waitrequest(),.ready(ready[3]),
.readdatavalid(rdv[3]), .broadcast(broadcast & write),
.write(writec[3]),.writedata(writedatac[3]));
plot_pixel #(.ID(5),.WAITV(WAIT)) p4(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[4]),.waitrequest(),.ready(ready[4]),
.readdatavalid(rdv[4]), .broadcast(broadcast & write),
.write(writec[4]),.writedata(writedatac[4]));
plot_pixel #(.ID(6),.WAITV(WAIT)) p5(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[5]),.waitrequest(),.ready(ready[5]),
.readdatavalid(rdv[5]), .broadcast(broadcast & write),
.write(writec[5]),.writedata(writedatac[5]));
plot_pixel #(.ID(7),.WAITV(WAIT)) p6(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[6]),.waitrequest(),.ready(ready[6]),
.readdatavalid(rdv[6]), .broadcast(broadcast & write),
.write(writec[6]),.writedata(writedatac[6]));
plot_pixel #(.ID(8),.WAITV(WAIT)) p7(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[7]),.waitrequest(),.ready(ready[7]),
.readdatavalid(rdv[7]), .broadcast(broadcast & write),
.write(writec[7]),.writedata(writedatac[7]));
plot_pixel #(.ID(9),.WAITV(WAIT)) p8(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[8]),.waitrequest(),.ready(ready[8]),
.readdatavalid(rdv[8]), .broadcast(broadcast & write),
.write(writec[8]),.writedata(writedatac[8]));
plot_pixel #(.ID(10),.WAITV(WAIT)) p9(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[9]),.waitrequest(),.ready(ready[9]),
.readdatavalid(rdv[9]), .broadcast(broadcast & write),
.write(writec[9]),.writedata(writedatac[9]));
plot_pixel #(.ID(11),.WAITV(WAIT)) p10(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[10]),.waitrequest(),.ready(ready[10]),
.readdatavalid(rdv[10]), .broadcast(broadcast & write),
.write(writec[10]),.writedata(writedatac[10]));
plot_pixel #(.ID(12),.WAITV(WAIT)) p11(.clk(clksel),.reset(reset),.read(readcircle),.address(address),
.readdata(rd[11]),.waitrequest(),.ready(ready[11]),
.readdatavalid(rdv[11]), .broadcast(broadcast & write),
.write(writec[11]),.writedata(writedatac[11]));
endmodule
// circle module
module plot_pixel
#(
parameter DATAW=18,
parameter ID=1,
parameter WAITV=5'h0
)
(
input clk,
input reset,
input broadcast,
output ready,
// mem mapped slave
// read
input read,
input [DATAW-1:0]address ,
output[7:0] readdata,
output waitrequest,
output readdatavalid,
// write
input write,
input[31:0] writedata
);
localparam WAIT=5'h0,COMPUTE=5'h1,
WRITE0=5'h3,
WRITE1=5'h4,
WRITE2=5'h5,
WRITE3=5'h6,
READING=5'h7;
reg[8:0] rx,ry;
reg signed[9:0] x,y, _x,_y, tempx;
reg signed[10:0] xp,_xp;
reg[7:0] radius;
reg lread;
reg[4:0] state,_state, istate,_istate;
reg we_a, we_b;
wire[7:0] q_a, q_b;
reg[DATAW-4:0] addr_a, addr_b;
assign waitrequest = 1'b0;
assign readdatavalid = (lread);
assign readdata = q_a;
wire tome, toall;
assign tome = ~broadcast;
assign toall = broadcast;
wire[8:0] xpx,xpy,xmx,xmy,_xpy,_xpx;
assign xpx = (rx + x[8:0]);
assign xpy = (rx + y[8:0]);
assign xmx = (rx - x[8:0]);
assign xmy = (rx - y[8:0]);
assign _xpx = (rx + _x[8:0]);
assign _xpy = (rx + _y[8:0]);
assign ready = (state == WAIT) ? 1'b1 : 1'b0;
reg[7:0] ramvala,ramvalb;
// Internal memory
true_dual_port_ram_single_clock #( .DATA_WIDTH(8), .ADDR_WIDTH((DATAW-3)))
ram0 (.data_a(ramvala), .data_b(ramvalb), .addr_a(addr_a), .addr_b(addr_b),
.we_a(we_a), .we_b(we_b), .clk(clk),
.q_a(q_a), .q_b(q_b));
// Data path
always@(posedge clk, posedge reset)
begin
if (reset)
begin
rx <= 0;
ry <= 0;
y <= 0;
x <= 0;
state <= WAIT;
istate <= WAIT;
lread <= 0;
end
else
begin
lread <= read;
if(write & tome)
begin
rx <= writedata [DATAW/2-1:0];
ry <= writedata [DATAW-1:DATAW/2];
radius <= writedata [DATAW-1+8:DATAW];
x <= writedata [DATAW-1+8:DATAW];
xp <= -{3'h0,writedata [DATAW-1+8:DATAW]} + 1'b1;
y <= 0;
state <= WRITE0;
istate <= READING;
end
else
begin
istate <= _istate;
state <= _state;
x <= _x;
y <= _y;
xp <= _xp;
end
end
end
// Control logic and FSM
always@*
begin
_x = x;
_y = y;
_xp = xp;
_state = state;
ramvala = (write&(toall)) ? writedata[7:0] : 8'h0;
ramvalb = (write&(toall)) ? writedata[7:0] : 8'h0;
we_a = write&toall;
we_b = write&toall;
_istate = istate;
addr_a = address[DATAW-4:0];
addr_b = address[DATAW-4:0];
case (state)
WAIT:
begin
end
COMPUTE:
begin
_y = y + 1'b1;
if(xp < 0)
begin
_xp = xp + {_y,1'b0} + 1'b1;
end
else
begin
_x = x - 1'b1;
_xp = xp + {(_y-_x),1'b0} + 1'b1;
end
if(_x >= _y && radius != 0)
begin
addr_a = { (ry + _y[8:0] ), _xpx[8:3]};
addr_b = { (ry + _x[8:0]), _xpy[8:3] };
_state = WRITE0;
_istate = WRITE0;
end
else
begin
_state = WAIT;
end
end
WRITE0:
begin
addr_a = { (ry + y[8:0] ), xpx[8:3] };
addr_b = { (ry + x[8:0] ), xpy[8:3] };
if (istate == READING)
begin
_istate = state;
end
else
begin
{we_a,we_b} = 2'b11;
ramvala = ( 1'b1 << xpx[2:0] ) | q_a;
ramvalb = ( 1'b1 << xpy[2:0] ) | q_b;
_state = WRITE1;
_istate = READING;
end
end
WRITE1:
begin
addr_a = { (ry - y[8:0] ), xpx[8:3] };
addr_b = { (ry - x[8:0] ), xpy[8:3] };
if (istate == READING)
begin
_istate = state;
end
else
begin
{we_a,we_b} = 2'b11;
ramvala = ( 1'b1 << xpx[2:0] ) | q_a;
ramvalb = ( 1'b1 << xpy[2:0] ) | q_b;
_state = WRITE2;
_istate = READING;
end
end
WRITE2:
begin
addr_a = { (ry + y[8:0] ), xmx[8:3] };
addr_b = { (ry + x[8:0] ), xmy[8:3] };
if (istate == READING)
begin
_istate = state;
end
else
begin
{we_a,we_b} = 2'b11;
ramvala = ( 1'b1 << xmx[2:0] ) | q_a;
ramvalb = ( 1'b1 << xmy[2:0] ) | q_b;
_state = WRITE3;
_istate = READING;
end
end
WRITE3:
begin
addr_a = { (ry - y[8:0] ), xmx[8:3] };
addr_b = { (ry - x[8:0] ), xmy[8:3] };
if (istate == READING)
begin
_istate = state;
end
else
begin
{we_a,we_b} = 2'b11;
ramvala = ( 1'b1 << xmx[2:0] ) | q_a;
ramvalb = ( 1'b1 << xmy[2:0] ) | q_b;
_state = COMPUTE;
_istate = READING;
end
end
endcase
end
endmodule
// Quartus II Verilog Template
// True Dual Port RAM with single clock
module true_dual_port_ram_single_clock
#(parameter DATA_WIDTH=8, parameter ADDR_WIDTH=6)
(
input [(DATA_WIDTH-1):0] data_a, data_b,
input [(ADDR_WIDTH-1):0] addr_a, addr_b,
input we_a, we_b, clk,
output reg [(DATA_WIDTH-1):0] q_a, q_b
);
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
// Port A
always @ (posedge clk)
begin
if (we_a)
begin
ram[addr_a] <= data_a;
q_a <= data_a;
end
else
begin
q_a <= ram[addr_a];
end
end
// Port B
always @ (posedge clk)
begin
if (we_b)
begin
ram[addr_b] <= data_b;
q_b <= data_b;
end
else
begin
q_b <= ram[addr_b];
end
end
endmodule