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:
parent
29bc2e6d96
commit
aedefddb5d
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
);
|
||||
|
||||
/*############################################################################### */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user