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...
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}
${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
${QUIET_NEXTPNR}

View File

@ -39,7 +39,7 @@ wire [19:0] address_bus;
wire [15:0] data_bus_read,data_bus_write;
wire rd,wr,BHE,IOMEM;
wire CPU_SPEED=counter[6];
wire CPU_SPEED=clk48;
system system(
/* MISC */ CPU_SPEED,reset
@ -95,99 +95,21 @@ always @(posedge counter[15]) begin
endcase
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
// chance to keep up with the relentless CPU
reg [5:0] disp_cache_start=0;
reg [5:0] disp_cache_end=0;
reg [7:0] disp_write_cache [63:0];
reg [6:0] disp_cache_start=0;
reg [6:0] disp_cache_end=0;
reg [7:0] disp_write_cache [127:0];
reg ascii_state=0;
always @(posedge CPU_SPEED)begin
if(wr==0)begin
if(IOMEM==1'b1 && address_bus[7:0]==8'hA5 )begin
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
if(data_bus_write[0:0]==1)
rgb_led_color=3'b000;
@ -197,7 +119,7 @@ always @(posedge CPU_SPEED)begin
end else if(ascii_state==1'b0)begin
if(ascii_data_ready&disp_cache_start!=disp_cache_end)begin
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_state<=1'b1;
end

View File

@ -19,7 +19,7 @@
/* This warning is because we don't use the full address bus. */
/* 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 */
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
always @(negedge wr) begin
if( cs == 0 ) begin
always @(posedge clock) begin
if( cs == 0 && wr == 0) begin
if(BHE==0)
memory[address[16:1]][7:0]<=cpu_write_data[15:8];
if(address[0]==0)

View File

@ -121,62 +121,6 @@ always @(posedge clock) begin
in_data_ready<=1;
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
if(next_line)begin
case(line)

View File

@ -194,7 +194,8 @@ register_file register_file(
/* READ 1 */ .read_port1_addr(reg_read_port1_addr),
/* */ .read_port1_data(reg_read_port1_data),
/* 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:
* [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] read_port1_addr;
input [3:0] read_port2_addr;
@ -48,47 +49,48 @@ assign read_port2_data[7:0] = ( read_port2_addr[3:3] ? registers[read_port2_addr
wire write_Wbit;
assign write_Wbit=write_port1_addr[3:3];
always @(negedge write_port1_we) begin
if(write_Wbit==1)begin
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
registers[write_port1_addr[2:0]] <= write_port1_data;
end else begin
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
if(write_port1_addr[2:2]==1)begin
/* Byte */
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
always @(posedge clock) begin
if(write_port1_we==0)begin
if(write_Wbit==1)begin
/* Word : AX,CX,DX,BX,SP,BP,SI,DI */
registers[write_port1_addr[2:0]] <= write_port1_data;
end else begin
/* Byte */
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
/* Byte : AL,CL,DL,BL,AX,CX,DX,BX */
if(write_port1_addr[2:2]==1)begin
/* Byte */
registers[ {1'b0,write_port1_addr[1:0]} ][15:8] <= write_port1_data[7:0];
end else begin
/* Byte */
registers[ {1'b0,write_port1_addr[1:0]} ][7:0] <= write_port1_data[7:0];
end
end
`ifdef DEBUG_REG_WRITES
// Icarus Verilog really doesn't like non-blocking assignments
// here
/* verilator lint_off BLKSEQ */
if(write_port1_addr[3:2]==2'b11)begin
case(write_port1_addr[1:0])
2'b00: debug_name="sp";
2'b01: debug_name="bp";
2'b10: debug_name="si";
2'b11: debug_name="di";
endcase
end else begin
case(write_port1_addr[1:0])
2'b00: debug_name="ax";
2'b01: debug_name="cx";
2'b10: debug_name="dx";
2'b11: debug_name="bx";
endcase
end
/* verilator lint_on BLKSEQ */
if (write_Wbit)
debug_address<=write_port1_addr[2:0];
else
debug_address<={1'b0,write_port1_addr[1:0]};
`endif
end
`ifdef DEBUG_REG_WRITES
// Icarus Verilog really doesn't like non-blocking assignments
// here
/* verilator lint_off BLKSEQ */
if(write_port1_addr[3:2]==2'b11)begin
case(write_port1_addr[1:0])
2'b00: debug_name="sp";
2'b01: debug_name="bp";
2'b10: debug_name="si";
2'b11: debug_name="di";
endcase
end else begin
case(write_port1_addr[1:0])
2'b00: debug_name="ax";
2'b01: debug_name="cx";
2'b10: debug_name="dx";
2'b11: debug_name="bx";
endcase
end
/* verilator lint_on BLKSEQ */
if (write_Wbit)
debug_address<=write_port1_addr[2:0];
else
debug_address<={1'b0,write_port1_addr[1:0]};
`endif
end
`ifdef DEBUG_REG_WRITES

View File

@ -49,7 +49,7 @@ processor p(
`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
string stats_name,version,commit;