Project: The cpu finally works perfectly now even at full speed as far as i can tell! I made the ram and register writes synchronous which fixed the weird issues I had, then I added -abc9 to yosys so that nextpnr can actually route the cpu at full speed and increased the display fifo since the cpu is so fast now!!

This commit is contained in:
(Tim) Efthimis Kritikos 2023-11-15 18:43:03 +00:00
parent 29bc2e6d96
commit aedefddb5d
7 changed files with 54 additions and 185 deletions

View File

@ -77,7 +77,7 @@ simplified_ucode.txt:ucode.txt
#TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program... #TODO: we are relying on yosys to trim the input program txt file and hope its enough for the whole program...
synth_ecp5.json: ${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${INCLUDES} ../boot_code/brainfuck_compiled.txt simplified_ucode.txt synth_ecp5.json: ${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ${INCLUDES} ../boot_code/brainfuck_compiled.txt simplified_ucode.txt
${QUIET_YOSYS} ${QUIET_YOSYS}
${Q} yosys -q -D BUILTIN_RAM=2048 -D NOT_FULL -p 'read -sv '"${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ; synth_ecp5 -json $@ -top fpga_top" ${Q} yosys -q -D BUILTIN_RAM=2048 -D NOT_FULL -p 'read -sv '"${SOURCES} ${TOP_LEVEL_SOURCE} fpga_config/${FPGA_BOARD}/fpga_top.v ${EXTRA_SYNTHESIS_SOURCES} ; synth_ecp5 -json $@ -abc9 -top fpga_top"
synth_ecp5_out.config:synth_ecp5.json synth_ecp5_out.config:synth_ecp5.json
${QUIET_NEXTPNR} ${QUIET_NEXTPNR}

View File

@ -39,7 +39,7 @@ wire [19:0] address_bus;
wire [15:0] data_bus_read,data_bus_write; wire [15:0] data_bus_read,data_bus_write;
wire rd,wr,BHE,IOMEM; wire rd,wr,BHE,IOMEM;
wire CPU_SPEED=counter[6]; wire CPU_SPEED=clk48;
system system( system system(
/* MISC */ CPU_SPEED,reset /* MISC */ CPU_SPEED,reset
@ -95,99 +95,21 @@ always @(posedge counter[15]) begin
endcase endcase
end end
/* TODO This seems to be a bug with YOSYS. If I don't initialise the memory
* it doesn't work (even though it does in sim), and for example if i
* initialise 1 twice to the same value it breaks again.
*
* This seems to affect brainfuck_compiled.asm and specifically when the
* compiled code starts running ( or the compiler i guess )
*/
initial begin
disp_write_cache[ 0]=8'h46;
disp_write_cache[ 1]=8'h46;
disp_write_cache[ 2]=8'h46;
disp_write_cache[ 3]=8'h46;
disp_write_cache[ 4]=8'h46;
disp_write_cache[ 5]=8'h46;
disp_write_cache[ 6]=8'h46;
disp_write_cache[ 7]=8'h46;
disp_write_cache[ 8]=8'h46;
disp_write_cache[ 9]=8'h46;
disp_write_cache[10]=8'h46;
disp_write_cache[11]=8'h46;
disp_write_cache[12]=8'h46;
disp_write_cache[13]=8'h46;
disp_write_cache[14]=8'h46;
disp_write_cache[15]=8'h46;
disp_write_cache[16]=8'h46;
disp_write_cache[17]=8'h46;
disp_write_cache[18]=8'h46;
disp_write_cache[19]=8'h46;
disp_write_cache[20]=8'h46;
disp_write_cache[21]=8'h46;
disp_write_cache[22]=8'h46;
disp_write_cache[23]=8'h46;
disp_write_cache[24]=8'h46;
disp_write_cache[25]=8'h46;
disp_write_cache[26]=8'h46;
disp_write_cache[27]=8'h46;
disp_write_cache[28]=8'h46;
disp_write_cache[29]=8'h46;
disp_write_cache[30]=8'h46;
disp_write_cache[31]=8'h46;
disp_write_cache[32]=8'h46;
disp_write_cache[33]=8'h46;
disp_write_cache[34]=8'h46;
disp_write_cache[35]=8'h46;
disp_write_cache[36]=8'h46;
disp_write_cache[37]=8'h46;
disp_write_cache[38]=8'h46;
disp_write_cache[39]=8'h46;
disp_write_cache[40]=8'h46;
disp_write_cache[41]=8'h46;
disp_write_cache[42]=8'h46;
disp_write_cache[43]=8'h46;
disp_write_cache[44]=8'h46;
disp_write_cache[45]=8'h46;
disp_write_cache[46]=8'h46;
disp_write_cache[47]=8'h46;
disp_write_cache[48]=8'h46;
disp_write_cache[49]=8'h46;
disp_write_cache[50]=8'h46;
disp_write_cache[51]=8'h46;
disp_write_cache[52]=8'h46;
disp_write_cache[53]=8'h46;
disp_write_cache[54]=8'h46;
disp_write_cache[55]=8'h46;
disp_write_cache[56]=8'h46;
disp_write_cache[57]=8'h46;
disp_write_cache[58]=8'h46;
disp_write_cache[59]=8'h46;
disp_write_cache[60]=8'h46;
disp_write_cache[61]=8'h46;
disp_write_cache[62]=8'h46;
disp_write_cache[63]=8'h46;
end
//TODO similarly as above, if I remove this the same thing breaks
always @(negedge wr) begin
end
//------------------------------------------// //------------------------------------------//
// Cache to allow the slow display to have a // Cache to allow the slow display to have a
// chance to keep up with the relentless CPU // chance to keep up with the relentless CPU
reg [5:0] disp_cache_start=0; reg [6:0] disp_cache_start=0;
reg [5:0] disp_cache_end=0; reg [6:0] disp_cache_end=0;
reg [7:0] disp_write_cache [63:0]; reg [7:0] disp_write_cache [127:0];
reg ascii_state=0; reg ascii_state=0;
always @(posedge CPU_SPEED)begin always @(posedge CPU_SPEED)begin
if(wr==0)begin if(wr==0)begin
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
disp_write_cache[disp_cache_end]<=data_bus_write[15:8]; disp_write_cache[disp_cache_end]<=data_bus_write[15:8];
disp_cache_end<=disp_cache_end+6'd1; disp_cache_end<=disp_cache_end+7'd1;
end else if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin end else if(IOMEM==1'b1 && address_bus[7:0]==8'hB0 )begin
if(data_bus_write[0:0]==1) if(data_bus_write[0:0]==1)
rgb_led_color=3'b000; rgb_led_color=3'b000;
@ -197,7 +119,7 @@ always @(posedge CPU_SPEED)begin
end else if(ascii_state==1'b0)begin end else if(ascii_state==1'b0)begin
if(ascii_data_ready&disp_cache_start!=disp_cache_end)begin if(ascii_data_ready&disp_cache_start!=disp_cache_end)begin
ascii_data<=disp_write_cache[disp_cache_start]; ascii_data<=disp_write_cache[disp_cache_start];
disp_cache_start<=disp_cache_start+6'd1; disp_cache_start<=disp_cache_start+7'd1;
ascii_data_write_req<=1; ascii_data_write_req<=1;
ascii_state<=1'b1; ascii_state<=1'b1;
end end

View File

@ -19,7 +19,7 @@
/* This warning is because we don't use the full address bus. */ /* This warning is because we don't use the full address bus. */
/* verilator lint_off UNUSEDSIGNAL */ /* verilator lint_off UNUSEDSIGNAL */
module doublemem(input [19:0] address,output [15:0] cpu_read_data ,input [15:0] cpu_write_data,input rd,input wr,input BHE,input cs); module doublemem(input [19:0] address,output [15:0] cpu_read_data ,input [15:0] cpu_write_data,input rd,input wr,input BHE,input cs,input clock);
/* verilator lint_on UNUSEDSIGNAL */ /* verilator lint_on UNUSEDSIGNAL */
reg [15:0] memory [0:`BUILTIN_RAM]; reg [15:0] memory [0:`BUILTIN_RAM];
@ -58,8 +58,8 @@ assign cpu_read_data[15:8] = !BHE & !rd & !cs ? (address[15:4]==12'b1111
`endif `endif
always @(negedge wr) begin always @(posedge clock) begin
if( cs == 0 ) begin if( cs == 0 && wr == 0) begin
if(BHE==0) if(BHE==0)
memory[address[16:1]][7:0]<=cpu_write_data[15:8]; memory[address[16:1]][7:0]<=cpu_write_data[15:8];
if(address[0]==0) if(address[0]==0)

View File

@ -121,62 +121,6 @@ always @(posedge clock) begin
in_data_ready<=1; in_data_ready<=1;
end end
end end
////////////////////////////////////////////////
/* TODO: These are unreachable states but from
* what i assume to be a bug in yosys. They need
* to be here for brainfuck_compiled.asm to work.
* Specifically for the compiled program to not output
* random characters.
*/
8'd14:begin
data<=4'hf;
next_line<=1;
if(!done_writing)begin
driver_state<=8'd1;
write_req<=1'b0;
end else
write_req<=1'b1;
end
8'd13:begin
data<=4'hf;
if(!done_writing)begin
driver_state<=8'd1;
write_req<=1'b0;
end else
write_req<=1'b1;
end
8'd1:begin
if(done_writing==1)
driver_state<=8'd2;
end
8'd2:begin
data<=4'hE;
if(!done_writing)begin
driver_state<=8'd3;
write_req<=1'b0;
end else
write_req<=1'b1;
end
8'd3:begin
if(done_writing==1)
driver_state<=8'd4;
end
8'd4:begin
data<=4'h0;
cmd_data<=1'b0;
if(!done_writing)begin
driver_state<=8'd5;
write_req<=1'b0;
end else
write_req<=1'b1;
end
8'd5:begin
if(done_writing==1)
driver_state<=8'd6;
end
////////////////////////////////////////////////
8'd6:begin 8'd6:begin
if(next_line)begin if(next_line)begin
case(line) case(line)

View File

@ -194,7 +194,8 @@ register_file register_file(
/* READ 1 */ .read_port1_addr(reg_read_port1_addr), /* READ 1 */ .read_port1_addr(reg_read_port1_addr),
/* */ .read_port1_data(reg_read_port1_data), /* */ .read_port1_data(reg_read_port1_data),
/* READ 2 */ .read_port2_addr(DE_reg_read_port2_addr), /* READ 2 */ .read_port2_addr(DE_reg_read_port2_addr),
/* */ .read_port2_data(reg_read_port2_data) /* */ .read_port2_data(reg_read_port2_data),
/* GENERAL */ .clock(clock)
); );
/*############################################################################### */ /*############################################################################### */

View File

@ -21,7 +21,8 @@
/* Register address format: /* Register address format:
* [W-bit] [ 3-bit address] */ * [W-bit] [ 3-bit address] */
module register_file (write_port1_addr,write_port1_data,write_port1_we,read_port1_addr,read_port1_data,read_port2_addr,read_port2_data); module register_file (write_port1_addr,write_port1_data,write_port1_we,read_port1_addr,read_port1_data,read_port2_addr,read_port2_data,clock);
input clock;
input [3:0] write_port1_addr; input [3:0] write_port1_addr;
input [3:0] read_port1_addr; input [3:0] read_port1_addr;
input [3:0] read_port2_addr; input [3:0] read_port2_addr;
@ -48,7 +49,8 @@ assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr
wire write_Wbit; wire write_Wbit;
assign write_Wbit=write_port1_addr[3:3]; assign write_Wbit=write_port1_addr[3:3];
always @(negedge write_port1_we) begin always @(posedge clock) begin
if(write_port1_we==0)begin
if(write_Wbit==1)begin if(write_Wbit==1)begin
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */ /* Word : AX,CX,DX,BX,SP,BP,SI,DI */
registers[write_port1_addr[2:0]] <= write_port1_data; registers[write_port1_addr[2:0]] <= write_port1_data;
@ -88,7 +90,7 @@ always @(negedge write_port1_we) begin
debug_address<={1'b0,write_port1_addr[1:0]}; debug_address<={1'b0,write_port1_addr[1:0]};
`endif `endif
end
end end
`ifdef DEBUG_REG_WRITES `ifdef DEBUG_REG_WRITES

View File

@ -49,7 +49,7 @@ processor p(
`endif `endif
); );
doublemem sysmem(address_bus,data_bus_read_,data_bus_write_,rd,wr,BHE,IOMEM); doublemem sysmem(address_bus,data_bus_read_,data_bus_write_,rd,wr,BHE,IOMEM,clock);
`ifdef OUTPUT_JSON_STATISTICS `ifdef OUTPUT_JSON_STATISTICS
string stats_name,version,commit; string stats_name,version,commit;