Permalink
Cannot retrieve contributors at this time
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?
codesign-challenge-2015/final-design/codesign_challenge/verilog/plot_circle.v
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
601 lines (506 sloc)
14.4 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |