├── AudioTut ├── A2D_intf.sv ├── AudioScale.sv ├── AudioTut.qpf ├── AudioTut.qsf ├── AudioTut.v ├── AudioTutorial554.pdf ├── CODEC_cfg.sv ├── CODEC_cfg_tb.sv ├── DP_RAM120x16.sv ├── DrawLogic.sv ├── I2C24Wrt.sv ├── I2C_tb.sv ├── PLL.v ├── SPI_M.sv ├── VGA_timing.sv ├── codec_intf.sv └── rst_synch.v ├── BMP_display ├── BMP.asm ├── BMP.hex ├── BMP_ROM_Bucky.v ├── BMP_ROM_Font.v ├── BMP_ROM_Mario.v ├── BMP_ROM_madisonCapitol.v ├── BMP_display.qpf ├── BMP_display.qsf ├── BMP_display.sv ├── Bucky.hex ├── CapabilityExploreBMP.pdf ├── Font.hex ├── Mario24.hex ├── PLL.ppf ├── PLL.qip ├── PLL.sip ├── PLL.spd ├── PLL.v ├── PLL │ ├── PLL_0002.qip │ └── PLL_0002.v ├── PlaceBMP.sv ├── UART_rx.sv ├── UART_tx.sv ├── VGA_timing.sv ├── alu.v ├── bmp24_to_hex9.pl ├── br_bool.v ├── common_params.inc ├── cpu.v ├── cpu_tb.v ├── data_mem.v ├── dst_mux.v ├── dualPort16x16.sv ├── fifo.sv ├── id.v ├── instr_mem.v ├── madisonCapitol.bmp ├── madisonCapitol.hex ├── madisonCapitol.pgm ├── prgm_cntr.v ├── report_JQ_HZ_HQ_QL.txt ├── rf.v ├── rst_synch.v ├── spart.sv ├── src_mux.v └── videoMem.sv ├── DE1_SoC_CAMERA_Sol ├── DE1_SoC_CAMERA.qpf ├── DE1_SoC_CAMERA.qsf ├── DE1_SoC_CAMERA.sdc ├── DE1_SoC_CAMERA.v ├── RAW2GRAY.v ├── Sdram_Control │ ├── Sdram_Control.v │ ├── Sdram_Params.h │ ├── Sdram_RD_FIFO.qip │ ├── Sdram_RD_FIFO.v │ ├── Sdram_WR_FIFO.qip │ ├── Sdram_WR_FIFO.v │ ├── command.v │ ├── control_interface.v │ └── sdr_data_path.v └── v │ ├── CCD_Capture.v │ ├── I2C_CCD_Config.v │ ├── I2C_Controller.v │ ├── Line_Buffer1.bsf │ ├── Line_Buffer1.qip │ ├── Line_Buffer1.v │ ├── Reset_Delay.v │ ├── VGA_Controller.v │ ├── sdram_pll.bsf │ ├── sdram_pll.cmp │ ├── sdram_pll.ppf │ ├── sdram_pll.qip │ ├── sdram_pll.sip │ ├── sdram_pll.spd │ ├── sdram_pll.v │ ├── sdram_pll │ ├── sdram_pll_0002.qip │ └── sdram_pll_0002.v │ ├── sdram_pll_sim.f │ └── sdram_pll_sim │ ├── aldec │ └── rivierapro_setup.tcl │ ├── cadence │ ├── cds.lib │ ├── hdl.var │ └── ncsim_setup.sh │ ├── mentor │ └── msim_setup.tcl │ ├── sdram_pll.vo │ └── synopsys │ ├── vcs │ └── vcs_setup.sh │ └── vcsmx │ ├── synopsys_sim.setup │ └── vcsmx_setup.sh ├── ECE554_Final_Report.pdf ├── FPGA_Implementation_of_CNN_Handwritten_Character_Recognition.zip ├── Final_Presentation.pptx ├── MiniLab0 ├── Documentation │ ├── S2014_552_Project_description.pdf │ └── WISC-S14 ISA.pdf ├── ExampleASM_and_Assembler │ ├── BasicOpCodes1.asm │ ├── BasicOpCodes2.asm │ ├── BasicOpCodes3.asm │ ├── BasicOpCodes4.asm │ ├── Branchtown.asm │ ├── asmbl.pl │ ├── bubble.asm │ └── test3.asm ├── MiniLab0.sv ├── MiniLab0_tb.sv ├── Quartus │ ├── MiniLab0.htm │ ├── MiniLab0.qpf │ ├── MiniLab0.qsf │ └── MiniLab0.sdc ├── alu.v ├── assembly │ ├── asmbl.pl │ ├── complex.asm │ ├── complex.hex │ ├── demo.hex │ ├── instr.hex │ ├── load_sw_to_led.asm │ └── load_sw_to_led.hex ├── br_bool.v ├── common_params.inc ├── complex.asm ├── cpu.v ├── cpu_tb.v ├── data_mem.v ├── dst_mux.v ├── dualPort16x16.sv ├── id.v ├── instr_mem.v ├── miniproject0_552Proc.pdf ├── prgm_cntr.v ├── report.txt ├── rf.v ├── rst_synch.sv └── src_mux.v ├── MiniLab1 ├── MiniLab1.sv ├── MiniLab1_report_harry_justin.txt ├── QSF_FileGeneration.pdf ├── Quartus │ ├── MiniLab1.htm │ ├── MiniLab1.qpf │ ├── MiniLab1.qsf │ └── MiniLab1.sdc ├── UART.sv ├── UART_rx.sv ├── UART_tx.sv ├── alu.v ├── br_bool.v ├── common_params.inc ├── cpu.v ├── cpu_tb.v ├── data_mem.v ├── dst_mux.v ├── dualPort16x16.sv ├── fifo.sv ├── hello_world.asm ├── hello_world.hex ├── id.v ├── instr_mem.v ├── miniproject1.pdf ├── prgm_cntr.v ├── rf.v ├── rst_synch.sv ├── spart.sv ├── spart_tb.sv └── src_mux.v ├── Project ├── FP_modules │ ├── FP_add_tb.sv │ ├── FP_adder.sv │ ├── FP_adder_doc.txt │ ├── FP_mul.sv │ ├── FP_mul_tb.sv │ ├── FP_special_values.sv │ ├── float_to_signed_int.sv │ ├── float_to_signed_int_tb.sv │ ├── left_shifter.sv │ ├── right_shifter.sv │ ├── signed_int_to_float.sv │ └── signed_int_to_float_tb.sv ├── InOrderSuperscalarCPU │ ├── CPU_factory │ │ ├── module_test.cr.mti │ │ ├── module_test.mpf │ │ ├── ram_2p.qip │ │ ├── ram_2p.v │ │ ├── stack.sv │ │ ├── stack.sv.bak │ │ ├── stack_tb.sv │ │ ├── stack_tb.sv.bak │ │ ├── transcript │ │ ├── vsim.wlf │ │ └── work │ │ │ ├── @_opt │ │ │ ├── _data │ │ │ │ ├── exemptwh7ksi │ │ │ │ └── exemptwk1krk │ │ │ ├── _lib.qdb │ │ │ ├── _lib1_0.qdb │ │ │ ├── _lib1_0.qpg │ │ │ ├── _lib1_0.qtl │ │ │ ├── _lib2_0.qdb │ │ │ ├── _lib2_0.qpg │ │ │ ├── _lib2_0.qtl │ │ │ ├── _lib3_0.qdb │ │ │ ├── _lib3_0.qpg │ │ │ ├── _lib3_0.qtl │ │ │ ├── _lib4_0.qdb │ │ │ ├── _lib4_0.qpg │ │ │ ├── _lib4_0.qtl │ │ │ ├── _lib5_0.qdb │ │ │ ├── _lib5_0.qpg │ │ │ └── _lib5_0.qtl │ │ │ ├── _info │ │ │ ├── _lib.qdb │ │ │ ├── _lib1_0.qdb │ │ │ ├── _lib1_0.qpg │ │ │ ├── _lib1_0.qtl │ │ │ └── _vmake │ ├── FP_adder.sv │ ├── FP_mul.sv │ ├── alu.v │ ├── asmbl_32.pl │ ├── br_bool.v │ ├── common_params.inc │ ├── cpu.v │ ├── cpu_tb.v │ ├── data_mem.v │ ├── dst_mux.v │ ├── dualPort32x32.sv │ ├── eightKRAM_2p.qip │ ├── eightKRAM_2p.v │ ├── extended_ALU.sv │ ├── fifo.sv │ ├── float_to_signed_int.sv │ ├── id.v │ ├── instr.hex │ ├── instr_decode.sv │ ├── instr_mem.v │ ├── int_mul_16by16.sv │ ├── left_shifter.sv │ ├── prgm_cntr.v │ ├── ram_2p.qip │ ├── ram_2p.v │ ├── review_model_list.txt │ ├── rf.v │ ├── rf_6p.v │ ├── right_shifter.sv │ ├── rst_synch.v │ ├── signed_int_to_float.sv │ ├── src_mux.v │ └── stack.sv ├── ML │ ├── 1_epoch_suck_model │ │ ├── suckcon1.txt │ │ ├── suckcon2.txt │ │ ├── sucklin1.txt │ │ ├── sucklin2.txt │ │ ├── sucklin3.txt │ │ ├── suckpool1.txt │ │ ├── suckpool2.txt │ │ └── suckweightfix.hex │ ├── 1_epoch_test_model │ │ ├── test_con1.txt │ │ ├── test_con2.txt │ │ ├── test_fixed_image_cnn.hex │ │ ├── test_lin1.txt │ │ ├── test_lin2.txt │ │ ├── test_lin3.txt │ │ ├── test_pool1.txt │ │ ├── test_pool2.txt │ │ └── test_weightfix.hex │ ├── 20_epoch_good_model │ │ ├── goodcon1.txt │ │ ├── goodcon2.txt │ │ ├── goodlin1.txt │ │ ├── goodlin2.txt │ │ ├── goodlin3.txt │ │ ├── goodpool1.txt │ │ ├── goodpool2.txt │ │ └── goodweightfix.hex │ ├── 20_epoch_supercharged │ │ ├── fixed_image_cnn.hex │ │ ├── goodcon1.txt │ │ ├── goodcon2.txt │ │ ├── goodlin1.txt │ │ ├── goodlin2.txt │ │ ├── goodlin3.txt │ │ ├── goodpool1.txt │ │ ├── goodpool2.txt │ │ └── goodweightfix.hex │ ├── fixed_image.hex │ ├── fixed_image_cnn.hex │ └── train.ipynb ├── SourceCode │ ├── CCD_Capture.v │ ├── FP_adder.sv │ ├── FP_mul.sv │ ├── I2C_CCD_Config.v │ ├── I2C_Controller.v │ ├── ImageRecog.sv │ ├── Line_Buffer1.bsf │ ├── Line_Buffer1.qip │ ├── Line_Buffer1.v │ ├── PLL.bsf │ ├── PLL.cmp │ ├── PLL.ppf │ ├── PLL.qip │ ├── PLL.sip │ ├── PLL.spd │ ├── PLL.v │ ├── PLL │ │ ├── PLL_0002.qip │ │ └── PLL_0002.v │ ├── PLL_sim.f │ ├── PLL_sim │ │ ├── PLL.vo │ │ ├── aldec │ │ │ └── rivierapro_setup.tcl │ │ ├── cadence │ │ │ ├── cds.lib │ │ │ ├── hdl.var │ │ │ └── ncsim_setup.sh │ │ ├── mentor │ │ │ └── msim_setup.tcl │ │ └── synopsys │ │ │ ├── vcs │ │ │ └── vcs_setup.sh │ │ │ └── vcsmx │ │ │ ├── synopsys_sim.setup │ │ │ └── vcsmx_setup.sh │ ├── Quartus │ │ ├── ImageRecog.htm │ │ ├── ImageRecog.qpf │ │ ├── ImageRecog.qsf │ │ ├── ImageRecog.sdc │ │ ├── image_recog.mpf │ │ ├── ram_2p.qip │ │ ├── ram_2p.v │ │ └── work │ │ │ ├── _info │ │ │ ├── _lib.qdb │ │ │ └── _vmake │ ├── RAW2GRAY.v │ ├── Reset_Delay.v │ ├── Sdram_Control │ │ ├── Sdram_Control.v │ │ ├── Sdram_Params.h │ │ ├── Sdram_RD_FIFO.qip │ │ ├── Sdram_RD_FIFO.v │ │ ├── Sdram_WR_FIFO.qip │ │ ├── Sdram_WR_FIFO.v │ │ ├── command.v │ │ ├── control_interface.v │ │ └── sdr_data_path.v │ ├── UART_rx.sv │ ├── UART_tx.sv │ ├── VGA_Controller.v │ ├── alu.v │ ├── br_bool.v │ ├── common_params.inc │ ├── compress_request_system.sv │ ├── cpu.v │ ├── cpu_tb.sv │ ├── data_mem.v │ ├── dst_mux.v │ ├── dualPort32x32.sv │ ├── extended_ALU.sv │ ├── fifo.sv │ ├── float_to_signed_int.sv │ ├── id.v │ ├── image_compressor.sv │ ├── image_compressor_x.sv │ ├── image_mem.sv │ ├── instr.hex │ ├── instr_mem.v │ ├── int_mul_16by16.sv │ ├── left_shifter.sv │ ├── prgm_cntr.v │ ├── rf.v │ ├── right_shifter.sv │ ├── rst_synch.v │ ├── signed_int_to_float.sv │ ├── spart.sv │ ├── src_mux.v │ ├── stack.sv │ ├── test.py │ ├── test │ │ ├── FTI.asm │ │ ├── ITF.asm │ │ ├── add.asm │ │ ├── addf.asm │ │ ├── addi.asm │ │ ├── and.asm │ │ ├── asmbl_32.pl │ │ ├── branch.asm │ │ ├── jump.asm │ │ ├── llblhb.asm │ │ ├── lwsw.asm │ │ ├── mul.asm │ │ ├── mulf.asm │ │ ├── nor.asm │ │ ├── poppush.asm │ │ ├── sll.asm │ │ ├── sra.asm │ │ ├── srl.asm │ │ ├── sub.asm │ │ ├── subf.asm │ │ ├── subi.asm │ │ ├── test0.asm │ │ ├── test1.asm │ │ ├── test2.asm │ │ └── umul.asm │ ├── weight.hex │ ├── weight_cnn_rom.sv │ ├── weight_nn_rom.sv │ ├── weight_rom.sv │ ├── weightcnn.hex │ └── weightnn.hex ├── Specifications │ ├── ECE554_Final_Report.docx │ ├── ECE554_Interface_Document.docx │ ├── ISA.xlsx │ ├── ProjectOverview.pdf │ ├── ProjectProposalDoc554.docx │ ├── WISC-S14 ISA.pdf │ └── block diagram.pptx ├── asm_tests │ ├── ADDF.asm │ ├── ADDI.asm │ ├── FTI.asm │ ├── ITF.asm │ ├── MUL.asm │ ├── MULF.asm │ ├── PUSH_POP.asm │ ├── SUBF.asm │ ├── SUBI.asm │ ├── UMUL.asm │ ├── asmbl_32.pl │ ├── hello_world.asm │ └── translate_test.asm ├── firmware │ ├── CNN.asm │ ├── CNN_supercharged.asm │ ├── NN.asm │ ├── conv_func_readable.asm │ ├── linear_classification.asm │ └── naive_classification.asm ├── other_extended_modules │ ├── extended_ALU.sv │ ├── image_compressor.sv │ ├── image_compressor_tb.sv │ ├── image_compressor_x.sv │ ├── int_mul_16by16.sv │ ├── int_mul_16by16_tb.sv │ ├── stack.sv │ └── stack_tb.sv └── simulation │ ├── ImageRecog.sv │ ├── image_mem.sv │ └── top_tb.v ├── README.md └── demo_pic.jpg /AudioTut/AudioScale.sv: -------------------------------------------------------------------------------- 1 | module AudioScale(clk,rst_n,aud_vld,volume,lft_in,rht_in,lft_out,rht_out); 2 | 3 | input clk,rst_n; 4 | input signed [15:0] lft_in; 5 | input signed [15:0] rht_in; 6 | input aud_vld; 7 | input [11:0] volume; 8 | output reg [15:0] lft_out; 9 | output reg [15:0] rht_out; 10 | 11 | wire signed [27:0] prod_lft; // intermediate of scaling. 12 | wire signed [27:0] prod_rht; // intermediate of scaling. 13 | 14 | /////////////////////////////// 15 | // Scale by volume from A2D // 16 | ///////////////////////////// 17 | /// Ohh rats!! I had a 50/50 chance of wiring the pots correct 18 | /// Beauty of FPGA is you can correct mistakes like that 19 | /// scale by 12'hFFF - volume instead of volume 20 | assign prod_lft = lft_in*$signed(12'hFFF - {1'b0,volume}); 21 | assign prod_rht = rht_in*$signed(12'hFFF - {1'b0,volume}); 22 | 23 | 24 | /////////////////////////////////////// 25 | // Only update audio out on aud_vld // 26 | ///////////////////////////////////// 27 | always_ff @(posedge clk, negedge rst_n) 28 | if (!rst_n) begin 29 | lft_out <= 16'h0000; 30 | rht_out <= 16'h0000; 31 | end else if (aud_vld) begin 32 | lft_out <= prod_lft[27:12]; // div by 2048 33 | rht_out <= prod_rht[27:12]; // div by 2048 34 | end 35 | 36 | endmodule -------------------------------------------------------------------------------- /AudioTut/AudioTut.qpf: -------------------------------------------------------------------------------- 1 | DATE = "18:01:00 December 06, 2022" 2 | QUARTUS_VERSION = "15.1.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "AudioTut" 7 | -------------------------------------------------------------------------------- /AudioTut/AudioTutorial554.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/AudioTut/AudioTutorial554.pdf -------------------------------------------------------------------------------- /AudioTut/CODEC_cfg.sv: -------------------------------------------------------------------------------- 1 | module CODEC_cfg(clk,rst_n,SDA,SCL,cfg_done); 2 | 3 | input clk, rst_n; 4 | 5 | output reg cfg_done; 6 | output SCL; // I2C clock 7 | inout SDA; // I2C data 8 | 9 | // 7 16-bit commands to send 10 | localparam bit [15:0] cmds [0:6] = '{ 11 | 16'h0105, 12 | 16'h0305, 13 | 16'h0812, 14 | 16'h0A06, 15 | 16'h0C62, 16 | 16'h0E01, 17 | 16'h1201 18 | }; 19 | 20 | logic [17:0] timer; 21 | logic clr_timer; 22 | logic [2:0] idx; // index of current cmd being sent in the cmds array 23 | logic [15:0] cmd; 24 | logic inc_idx; 25 | logic wrt; 26 | logic done, err; // not used 27 | 28 | assign cmd = cmds[idx]; 29 | 30 | typedef enum logic [1:0] {IDLE, WCFG, WAIT, DONE} state_t; 31 | state_t state, nxt_state; 32 | 33 | // state reg 34 | always_ff @(posedge clk, negedge rst_n) 35 | if(!rst_n) 36 | state <= IDLE; 37 | else 38 | state <= nxt_state; 39 | 40 | // 18 bit timer 41 | always_ff @(posedge clk, negedge rst_n) 42 | if(!rst_n) 43 | timer <= '0; 44 | else if (clr_timer) 45 | timer <= '0; 46 | else 47 | timer <= timer + 1; 48 | 49 | // command index 50 | always_ff @(posedge clk, negedge rst_n) 51 | if(!rst_n) 52 | idx <= 3'b000; 53 | else if (inc_idx) 54 | idx <= idx + 1; 55 | 56 | // SM control 57 | always_comb begin 58 | inc_idx = 1'b0; 59 | wrt = 1'b0; 60 | cfg_done = 1'b0; 61 | clr_timer = 1'b0; 62 | nxt_state = state; 63 | 64 | case(state) 65 | IDLE: begin 66 | if(&timer) 67 | nxt_state = WCFG; 68 | end 69 | WCFG: begin 70 | wrt = 1'b1; 71 | clr_timer = 1'b1; 72 | nxt_state = WAIT; 73 | end 74 | WAIT: begin 75 | if(&timer[10:0]) begin // wait 2048 cycles for SPI transmission 76 | if(idx == 6) begin 77 | nxt_state = DONE; 78 | end 79 | else begin 80 | inc_idx = 1'b1; 81 | nxt_state = WCFG; 82 | end 83 | end 84 | end 85 | DONE: begin 86 | cfg_done = 1'b1; 87 | end 88 | endcase 89 | end 90 | 91 | ///////////////////////////// 92 | // Instantiate I2C Master // 93 | /////////////////////////// 94 | I2C24Wrt iDUT(.clk(clk),.rst_n(rst_n),.data16(cmd),.wrt(wrt),.done(done), 95 | .err(err),.SCL(SCL),.SDA(SDA)); 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /AudioTut/DP_RAM120x16.sv: -------------------------------------------------------------------------------- 1 | module DPRAM120x16(clk,we,waddr,wdata,raddr,rdata); 2 | 3 | input clk; 4 | input we; 5 | input [6:0] waddr; 6 | input [15:0] wdata; 7 | input [6:0] raddr; 8 | output reg [15:0] rdata; 9 | 10 | reg [15:0]mem[0:119]; 11 | 12 | always @(posedge clk) begin 13 | if (we) 14 | mem[waddr] <= wdata; 15 | rdata <= mem[raddr]; 16 | end 17 | 18 | endmodule -------------------------------------------------------------------------------- /AudioTut/I2C_tb.sv: -------------------------------------------------------------------------------- 1 | module I2C_tb(); 2 | 3 | reg clk,rst_n,wrt; 4 | reg [15:0] data; 5 | reg ack; 6 | 7 | wire SDA,SCL; 8 | wire done; 9 | wire err; 10 | 11 | assign (strong0,weak1) SDA = (ack) ? 1'b0 : 1'b1; 12 | 13 | ////////////////////// 14 | // Instantiate DUT // 15 | //////////////////// 16 | I2C24Wrt iDUT(.clk(clk),.rst_n(rst_n),.data16(data),.wrt(wrt),.done(done), 17 | .err(err),.SCL(SCL),.SDA(SDA)); 18 | 19 | initial begin 20 | rst_n = 0; 21 | clk = 0; 22 | data = 16'h6699; 23 | wrt = 0; 24 | ack = 0; 25 | @(negedge clk); 26 | rst_n = 1; 27 | 28 | repeat(100) @(posedge clk); 29 | wrt = 1; 30 | @(posedge clk); 31 | wrt = 0; 32 | 33 | repeat(9)@(posedge SCL); 34 | ack = 1; 35 | @(negedge SCL); 36 | ack = 0; 37 | 38 | repeat(9)@(posedge SCL); 39 | ack = 1; 40 | @(negedge SCL); 41 | ack = 0; 42 | 43 | repeat(9)@(posedge SCL); 44 | ack = 1; 45 | @(negedge SCL); 46 | ack = 0; 47 | 48 | @(posedge done); 49 | 50 | repeat(50) @(posedge clk); 51 | $stop(); 52 | 53 | 54 | end 55 | 56 | always 57 | #5 clk = ~clk; 58 | 59 | endmodule -------------------------------------------------------------------------------- /AudioTut/rst_synch.v: -------------------------------------------------------------------------------- 1 | module rst_synch(clk,RST_n,pll_locked,rst_n); 2 | 3 | input clk; // 50MHz clock 4 | input RST_n; // non synched reset from push button 5 | input pll_locked; // don't deassert reset till PLL is locked 6 | output reg rst_n; // synched on deassert to negedge of clock 7 | 8 | reg q1; 9 | 10 | //////////////////////////////////////////////// 11 | // rst_n is asserted asynch, but deasserted // 12 | // syncronized to negedge clock. Two flops // 13 | // are used for metastability purposes. // 14 | //////////////////////////////////////////// 15 | always @(negedge clk, negedge RST_n) 16 | if (!RST_n) 17 | begin 18 | q1 <= 1'b0; 19 | rst_n <= 1'b0; 20 | end 21 | else 22 | begin 23 | q1 <= pll_locked; 24 | rst_n <= q1; 25 | end 26 | 27 | endmodule -------------------------------------------------------------------------------- /BMP_display/BMP.hex: -------------------------------------------------------------------------------- 1 | @0000 B101 // LLB R1, 0x01 2 | @0001 B208 // LLB R2, 0x08 3 | @0002 A2C0 // LHB R2, 0xC0 4 | @0003 9021 // SW R0, R2, 1 5 | @0004 9022 // SW R0, R2, 2 6 | @0005 B380 // LLB R3, 0x80 7 | @0006 A329 // LHB R3, 0x29 8 | @0007 9320 // SW R3, R2, 0 9 | @0008 D04A // JAL wait 10 | @0009 B314 // LLB R3, 0x14 11 | @000a 9321 // SW R3, R2, 1 12 | @000b 9022 // SW R0, R2, 2 13 | @000c B300 // LLB R3, 0x00 14 | @000d A32D // LHB R3, 0x2D 15 | @000e 9320 // SW R3, R2, 0 16 | @000f D043 // JAL wait 17 | @0010 B33C // LLB R3, 0x3C 18 | @0011 9321 // SW R3, R2, 1 19 | @0012 9022 // SW R0, R2, 2 20 | @0013 B380 // LLB R3, 0x80 21 | @0014 A328 // LHB R3, 0x28 22 | @0015 9320 // SW R3, R2, 0 23 | @0016 D03C // JAL wait 24 | @0017 B350 // LLB R3, 0x50 25 | @0018 9321 // SW R3, R2, 1 26 | @0019 9022 // SW R0, R2, 2 27 | @001a B380 // LLB R3, 0x80 28 | @001b A331 // LHB R3, 0x31 29 | @001c 9320 // SW R3, R2, 0 30 | @001d D035 // JAL wait 31 | @001e B378 // LLB R3, 0x78 32 | @001f 9321 // SW R3, R2, 1 33 | @0020 9022 // SW R0, R2, 2 34 | @0021 B380 // LLB R3, 0x80 35 | @0022 A328 // LHB R3, 0x28 36 | @0023 9320 // SW R3, R2, 0 37 | @0024 D02E // JAL wait 38 | @0025 B38C // LLB R3, 0x8C 39 | @0026 A300 // LHB R3, 0x00 40 | @0027 9321 // SW R3, R2, 1 41 | @0028 9022 // SW R0, R2, 2 42 | @0029 B300 // LLB R3, 0x00 43 | @002a A32D // LHB R3, 0x2D 44 | @002b 9320 // SW R3, R2, 0 45 | @002c D026 // JAL wait 46 | @002d B3B4 // LLB R3, 0xB4 47 | @002e A300 // LHB R3, 0x00 48 | @002f 9321 // SW R3, R2, 1 49 | @0030 9022 // SW R0, R2, 2 50 | @0031 B300 // LLB R3, 0x00 51 | @0032 A32D // LHB R3, 0x2D 52 | @0033 9320 // SW R3, R2, 0 53 | @0034 D01E // JAL wait 54 | @0035 B3C8 // LLB R3, 0xC8 55 | @0036 A300 // LHB R3, 0x00 56 | @0037 9321 // SW R3, R2, 1 57 | @0038 9022 // SW R0, R2, 2 58 | @0039 B380 // LLB R3, 0x80 59 | @003a A32A // LHB R3, 0x2A 60 | @003b 9320 // SW R3, R2, 0 61 | @003c D016 // JAL wait 62 | @003d 9021 // SW R0, R2, 1 63 | @003e B332 // LLB R3, 0x32 64 | @003f 9322 // SW R3, R2, 2 65 | @0040 B340 // LLB R3, 0x40 66 | @0041 9320 // SW R3, R2, 0 67 | @0042 D010 // JAL wait 68 | @0043 B3C8 // LLB R3, 0xC8 69 | @0044 A300 // LHB R3, 0x00 70 | @0045 9321 // SW R3, R2, 1 71 | @0046 B332 // LLB R3, 0x32 72 | @0047 9322 // SW R3, R2, 2 73 | @0048 B341 // LLB R3, 0x41 74 | @0049 9320 // SW R3, R2, 0 75 | @004a D008 // JAL wait 76 | @004b B390 // LLB R3, 0x90 77 | @004c A301 // LHB R3, 0x01 78 | @004d 9321 // SW R3, R2, 1 79 | @004e B332 // LLB R3, 0x32 80 | @004f 9322 // SW R3, R2, 2 81 | @0050 B342 // LLB R3, 0x42 82 | @0051 9320 // SW R3, R2, 0 83 | @0052 F000 // HLT 84 | @0053 B400 // LLB R4, 0x00 85 | @0054 A410 // LHB R4, 0x10 86 | @0055 2441 // SUB R4, R4, R1 87 | @0056 C1FE // B neq, loop 88 | @0057 E0F0 // JR R15 89 | -------------------------------------------------------------------------------- /BMP_display/BMP_ROM_Bucky.v: -------------------------------------------------------------------------------- 1 | module BMP_ROM_Bucky(clk,addr,dout); 2 | 3 | input clk; // 50MHz clock 4 | input [15:0] addr; 5 | output reg [8:0] dout; // pixel out 6 | 7 | reg [8:0] rom[0:17169]; 8 | 9 | initial 10 | $readmemh("Bucky.hex",rom); 11 | 12 | always @(posedge clk) 13 | dout <= rom[addr]; 14 | 15 | endmodule 16 | -------------------------------------------------------------------------------- /BMP_display/BMP_ROM_Font.v: -------------------------------------------------------------------------------- 1 | module BMP_ROM_Font(clk,addr,dout); 2 | 3 | input clk; // 50MHz clock 4 | input [13:0] addr; 5 | output reg [8:0] dout; // pixel out 6 | 7 | reg [8:0] rom[0:8705]; 8 | 9 | initial 10 | $readmemh("Font.hex",rom); 11 | 12 | always @(posedge clk) 13 | dout <= rom[addr]; 14 | 15 | endmodule 16 | -------------------------------------------------------------------------------- /BMP_display/BMP_ROM_Mario.v: -------------------------------------------------------------------------------- 1 | module BMP_ROM_Mario(clk,addr,dout); 2 | 3 | input clk; // 50MHz clock 4 | input [15:0] addr; 5 | output reg [8:0] dout; // pixel out 6 | 7 | reg [8:0] rom[0:13249]; 8 | 9 | initial 10 | $readmemh("Mario24.hex",rom); 11 | 12 | always @(posedge clk) 13 | dout <= rom[addr]; 14 | 15 | endmodule 16 | -------------------------------------------------------------------------------- /BMP_display/BMP_ROM_madisonCapitol.v: -------------------------------------------------------------------------------- 1 | module BMP_ROM_madisonCapitol(clk,addr,dout); 2 | 3 | input clk; // 50MHz clock 4 | input [15:0] addr; 5 | output reg [8:0] dout; // 9-bit color pixel out 6 | 7 | reg [8:0] rom[0:5601]; 8 | 9 | initial 10 | $readmemh("madisonCapitol.hex",rom); 11 | 12 | always @(posedge clk) 13 | dout <= rom[addr]; 14 | 15 | endmodule 16 | -------------------------------------------------------------------------------- /BMP_display/BMP_display.qpf: -------------------------------------------------------------------------------- 1 | DATE = "18:01:00 December 06, 2022" 2 | QUARTUS_VERSION = "15.1.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "BMP_display" 7 | -------------------------------------------------------------------------------- /BMP_display/CapabilityExploreBMP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/BMP_display/CapabilityExploreBMP.pdf -------------------------------------------------------------------------------- /BMP_display/PLL.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BMP_display/PLL.sip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_VERSION "20.1" 3 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "lib_PLL" -name SPD_FILE [file join $::quartus(sip_path) "PLL.spd"] 5 | 6 | set_global_assignment -library "lib_PLL" -name MISC_FILE [file join $::quartus(sip_path) "PLL_sim/PLL.vo"] 7 | -------------------------------------------------------------------------------- /BMP_display/PLL.spd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /BMP_display/PLL/PLL_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 2 | 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /BMP_display/PLL/PLL_0002.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | module PLL_0002( 3 | 4 | // interface 'refclk' 5 | input wire refclk, 6 | 7 | // interface 'reset' 8 | input wire rst, 9 | 10 | // interface 'outclk0' 11 | output wire outclk_0, 12 | 13 | // interface 'outclk1' 14 | output wire outclk_1, 15 | 16 | // interface 'locked' 17 | output wire locked 18 | ); 19 | 20 | altera_pll #( 21 | .fractional_vco_multiplier("false"), 22 | .reference_clock_frequency("50.0 MHz"), 23 | .operation_mode("direct"), 24 | .number_of_clocks(2), 25 | .output_clock_frequency0("50.000000 MHz"), 26 | .phase_shift0("0 ps"), 27 | .duty_cycle0(50), 28 | .output_clock_frequency1("25.000000 MHz"), 29 | .phase_shift1("0 ps"), 30 | .duty_cycle1(50), 31 | .output_clock_frequency2("0 MHz"), 32 | .phase_shift2("0 ps"), 33 | .duty_cycle2(50), 34 | .output_clock_frequency3("0 MHz"), 35 | .phase_shift3("0 ps"), 36 | .duty_cycle3(50), 37 | .output_clock_frequency4("0 MHz"), 38 | .phase_shift4("0 ps"), 39 | .duty_cycle4(50), 40 | .output_clock_frequency5("0 MHz"), 41 | .phase_shift5("0 ps"), 42 | .duty_cycle5(50), 43 | .output_clock_frequency6("0 MHz"), 44 | .phase_shift6("0 ps"), 45 | .duty_cycle6(50), 46 | .output_clock_frequency7("0 MHz"), 47 | .phase_shift7("0 ps"), 48 | .duty_cycle7(50), 49 | .output_clock_frequency8("0 MHz"), 50 | .phase_shift8("0 ps"), 51 | .duty_cycle8(50), 52 | .output_clock_frequency9("0 MHz"), 53 | .phase_shift9("0 ps"), 54 | .duty_cycle9(50), 55 | .output_clock_frequency10("0 MHz"), 56 | .phase_shift10("0 ps"), 57 | .duty_cycle10(50), 58 | .output_clock_frequency11("0 MHz"), 59 | .phase_shift11("0 ps"), 60 | .duty_cycle11(50), 61 | .output_clock_frequency12("0 MHz"), 62 | .phase_shift12("0 ps"), 63 | .duty_cycle12(50), 64 | .output_clock_frequency13("0 MHz"), 65 | .phase_shift13("0 ps"), 66 | .duty_cycle13(50), 67 | .output_clock_frequency14("0 MHz"), 68 | .phase_shift14("0 ps"), 69 | .duty_cycle14(50), 70 | .output_clock_frequency15("0 MHz"), 71 | .phase_shift15("0 ps"), 72 | .duty_cycle15(50), 73 | .output_clock_frequency16("0 MHz"), 74 | .phase_shift16("0 ps"), 75 | .duty_cycle16(50), 76 | .output_clock_frequency17("0 MHz"), 77 | .phase_shift17("0 ps"), 78 | .duty_cycle17(50), 79 | .pll_type("General"), 80 | .pll_subtype("General") 81 | ) altera_pll_i ( 82 | .rst (rst), 83 | .outclk ({outclk_1, outclk_0}), 84 | .locked (locked), 85 | .fboutclk ( ), 86 | .fbclk (1'b0), 87 | .refclk (refclk) 88 | ); 89 | endmodule 90 | 91 | -------------------------------------------------------------------------------- /BMP_display/br_bool.v: -------------------------------------------------------------------------------- 1 | module br_bool(clk,rst_n,clk_z_ID_EX,clk_nv_ID_EX,br_instr_ID_EX, 2 | jmp_imm_ID_EX,jmp_reg_ID_EX,cc_ID_EX,zr,ov,neg, 3 | zr_EX_DM,flow_change_ID_EX); 4 | 5 | ////////////////////////////////////////////////////// 6 | // determines branch or not based on cc, and flags // 7 | //////////////////////////////////////////////////// 8 | input clk,rst_n; 9 | input clk_z_ID_EX; // from ID, tells us to flop the zero flag 10 | input clk_nv_ID_EX; // from ID, tells us to flop the overflow flag 11 | input br_instr_ID_EX; // from ID, tell us if this is a branch instruction 12 | input jmp_imm_ID_EX; // from ID, tell us this is jump immediate instruction 13 | input jmp_reg_ID_EX; // from ID, tell us this is jump register instruction 14 | input [2:0] cc_ID_EX; // condition code from instr[11:9] 15 | input zr,ov,neg; // flag bits from ALU 16 | 17 | output reg flow_change_ID_EX; // asserted if we should take branch or jumping 18 | output reg zr_EX_DM; // goes to ID for ADDZ 19 | 20 | reg neg_EX_DM,ov_EX_DM; 21 | 22 | ///////////////////////// 23 | // Flop for zero flag // 24 | /////////////////////// 25 | always @(posedge clk, negedge rst_n) 26 | if (!rst_n) 27 | zr_EX_DM <= 0; 28 | else if (clk_z_ID_EX) 29 | zr_EX_DM <= zr; 30 | 31 | 32 | ///////////////////////////////////// 33 | // Flops for negative and ov flag // 34 | /////////////////////////////////// 35 | always @(posedge clk, negedge rst_n) 36 | if (!rst_n) 37 | begin 38 | ov_EX_DM <= 0; 39 | neg_EX_DM <= 0; 40 | end 41 | else if (clk_nv_ID_EX) 42 | begin 43 | ov_EX_DM <= ov; 44 | neg_EX_DM <= neg; 45 | end 46 | 47 | always @(br_instr_ID_EX,cc_ID_EX,zr_EX_DM,ov_EX_DM,neg_EX_DM,jmp_reg_ID_EX,jmp_imm_ID_EX) begin 48 | 49 | flow_change_ID_EX = jmp_imm_ID_EX | jmp_reg_ID_EX; // jumps always change the flow 50 | 51 | if (br_instr_ID_EX) 52 | case (cc_ID_EX) 53 | 3'b000 : flow_change_ID_EX = ~zr_EX_DM; 54 | 3'b001 : flow_change_ID_EX = zr_EX_DM; 55 | 3'b010 : flow_change_ID_EX = ~zr_EX_DM & ~neg_EX_DM; 56 | 3'b011 : flow_change_ID_EX = neg_EX_DM; 57 | 3'b100 : flow_change_ID_EX = zr_EX_DM | (~zr_EX_DM & ~neg_EX_DM); 58 | 3'b101 : flow_change_ID_EX = neg_EX_DM | zr_EX_DM; 59 | 3'b110 : flow_change_ID_EX = ov_EX_DM; 60 | 3'b111 : flow_change_ID_EX = 1; 61 | endcase 62 | end 63 | 64 | endmodule -------------------------------------------------------------------------------- /BMP_display/common_params.inc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////// 3 | // Create defines for ALU functions // 4 | ///////////////////////////////////// 5 | localparam ADD = 3'b000; 6 | localparam SUB = 3'b001; 7 | localparam AND = 3'b010; 8 | localparam NOR = 3'b011; 9 | localparam SLL = 3'b100; 10 | localparam SRL = 3'b101; 11 | localparam SRA = 3'b110; 12 | localparam LHB = 3'b111; 13 | 14 | ////////////////////////////////////////// 15 | // Create defines for Opcode encodings // 16 | //////////////////////////////////////// 17 | localparam ADDi = 4'b0000; 18 | localparam ADDZi = 4'b0001; 19 | localparam SUBi = 4'b0010; 20 | localparam ANDi = 4'b0011; 21 | localparam NORi = 4'b0100; 22 | localparam SLLi = 4'b0101; 23 | localparam SRLi = 4'b0110; 24 | localparam SRAi = 4'b0111; 25 | localparam LWi = 4'b1000; 26 | localparam SWi = 4'b1001; 27 | localparam LHBi = 4'b1010; 28 | localparam LLBi = 4'b1011; 29 | localparam BRi = 4'b1100; 30 | localparam JALi = 4'b1101; 31 | localparam JRi = 4'b1110; 32 | localparam HLTi = 4'b1111; 33 | 34 | //////////////////////////////// 35 | // Encodings for src0 select // 36 | ////////////////////////////// 37 | localparam RF2SRC0 = 2'b00; 38 | localparam IMM_BR2SRC0 = 2'b01; // 7-bit SE for branch target 39 | localparam IMM_JMP2SRC0 = 2'b10; // 12-bit SE for jump target 40 | localparam IMM2SRC0 = 2'b11; // 4-bit SE Address immediate for LW/SW 41 | 42 | //////////////////////////////// 43 | // Encodings for src1 select // 44 | ////////////////////////////// 45 | localparam RF2SRC1 = 2'b00; 46 | localparam IMM2SRC1 = 2'b01; // 8-bit data immediate for LLB/LHB 47 | localparam NPC2SRC1 = 2'b10; // nxt_pc to src1 for JAL instruction 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /BMP_display/cpu_tb.v: -------------------------------------------------------------------------------- 1 | module cpu_tb(); 2 | 3 | reg clk,rst_n; 4 | 5 | ////////////////////// 6 | // Instantiate CPU // 7 | //////////////////// 8 | cpu iCPU(.clk(clk), .rst_n(rst_n)); 9 | 10 | initial begin 11 | clk = 0; 12 | rst_n = 0; 13 | #2 rst_n = 1; 14 | end 15 | 16 | always 17 | #1 clk = ~clk; 18 | 19 | endmodule -------------------------------------------------------------------------------- /BMP_display/data_mem.v: -------------------------------------------------------------------------------- 1 | module DM(clk,addr,re,we,wrt_data,rd_data); 2 | 3 | ///////////////////////////////////////////////////////// 4 | // Data memory. Single ported, can read or write but // 5 | // not both in a single cycle. Precharge on clock // 6 | // high, read/write on clock low. // 7 | ///////////////////////////////////////////////////// 8 | input clk; 9 | input [12:0] addr; 10 | input re; // asserted when instruction read desired 11 | input we; // asserted when write desired 12 | input [15:0] wrt_data; // data to be written 13 | 14 | output reg [15:0] rd_data; // output of data memory 15 | 16 | reg [15:0]data_mem[0:8192]; // 8K*16 data memory 17 | 18 | ///////////////////////////////////////// 19 | // Read is synchronous on negedge clk // 20 | /////////////////////////////////////// 21 | always @(negedge clk) 22 | if (re && ~we) 23 | rd_data <= data_mem[addr]; 24 | 25 | ///////////////////////////////////////////////// 26 | // Model write, data is written on clock fall // 27 | /////////////////////////////////////////////// 28 | always @(negedge clk) 29 | if (we && ~re) 30 | data_mem[addr] <= wrt_data; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /BMP_display/dst_mux.v: -------------------------------------------------------------------------------- 1 | module dst_mux(clk,dm_re_EX_DM,dm_rd_data_EX_DM,pc_EX_DM,dst_EX_DM,rf_w_data_DM_WB,jmp_imm_EX_DM); 2 | //////////////////////////////////////////////////////////////////////// 3 | // Simple 2:1 mux determining if ALU or DM is source for write to RF // 4 | ////////////////////////////////////////////////////////////////////// 5 | input clk; 6 | input dm_re_EX_DM; 7 | input jmp_imm_EX_DM; 8 | input [15:0] dm_rd_data_EX_DM; // input from DM 9 | input [15:0] pc_EX_DM; // from PC for JAL saving to R15 10 | input [15:0] dst_EX_DM; // input from ALU 11 | 12 | output reg[15:0] rf_w_data_DM_WB; // output to be written to RF 13 | 14 | always @(posedge clk) 15 | if (dm_re_EX_DM) 16 | rf_w_data_DM_WB <= dm_rd_data_EX_DM; 17 | else if (jmp_imm_EX_DM) 18 | rf_w_data_DM_WB <= pc_EX_DM; 19 | else 20 | rf_w_data_DM_WB <= dst_EX_DM; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /BMP_display/dualPort16x16.sv: -------------------------------------------------------------------------------- 1 | module dualPort16x16(clk,we,re,waddr,raddr,wdata,rdata); 2 | 3 | input clk; // system clock 4 | input we; // write enable 5 | input re; // read enable 6 | input [3:0] waddr; // write address 7 | input [3:0] raddr; // read address 8 | input [15:0] wdata; // data to write 9 | output reg [15:0] rdata; // read data output 10 | 11 | reg [15:0] mem [15:0]; // 16 by 16 SRAM block 12 | 13 | // negedge triggered memory 14 | always @(negedge clk) begin 15 | if(we) 16 | mem[waddr] <= wdata; 17 | if(re) 18 | rdata <= mem[raddr]; 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /BMP_display/fifo.sv: -------------------------------------------------------------------------------- 1 | // A fifo queue that allows read and write at same time 2 | module fifo( 3 | input clk, // 50MHz clk 4 | input rst_n, // asynch active low reset 5 | input w_en, // write enable 6 | input r_en, // read enable 7 | input [7:0] in_data, // data to be stored in queue 8 | output q_full, // indicates queue is full 9 | output q_empty, // indicates queue is empty 10 | output [7:0] out_data, // data to be read in queue 11 | output [3:0] contain_num // Number of used entires in the queue 12 | ); 13 | 14 | ///////////////////////////// 15 | // Declare reg and wires // 16 | /////////////////////////// 17 | reg [3:0] head_ptr, tail_ptr; // Insert into head, pop from tail 18 | reg [7:0] buffer [0:7]; // 8 entry buffer with 8bits wide data 19 | 20 | // When all 8 entries are filled, the lower 3 bits of the pointer will be same, but the highest bit will be different 21 | assign q_full = tail_ptr[2:0] == head_ptr[2:0] && tail_ptr[3] == ~head_ptr[3]; 22 | // When head ptr and tail ptr are same, the queue is empty 23 | assign q_empty = tail_ptr == head_ptr; 24 | // Number of used/filled entry in the queue 25 | assign contain_num = head_ptr - tail_ptr; 26 | 27 | ///////////////////////////////// 28 | // Read data from the buffer // 29 | /////////////////////////////// 30 | assign out_data = buffer[tail_ptr[2:0]]; //Constantly output the data from the tail_ptr 31 | 32 | /////////////////////////////////// 33 | // Write data into the buffer // 34 | ///////////////////////////////// 35 | always_ff @(posedge clk) 36 | if (w_en && !q_full) 37 | buffer[head_ptr[2:0]] <= in_data; 38 | 39 | /////////////////////////////// 40 | // Tail ptr control logic // 41 | ///////////////////////////// 42 | always_ff @(posedge clk, negedge rst_n) 43 | if (!rst_n) 44 | tail_ptr <= 4'h0; 45 | else if (r_en && !q_empty) // Increment tail_ptr when read enabled and queue is not empty 46 | tail_ptr <= tail_ptr + 4'h1; // Increment tail_ptr == pop an entry from the queue 47 | 48 | /////////////////////////////// 49 | // Head ptr control logic // 50 | ///////////////////////////// 51 | always_ff @(posedge clk, negedge rst_n) 52 | if (!rst_n) 53 | head_ptr <= 4'h0; 54 | else if (w_en && !q_full) // Increment head ptr when write enabled and queue is not full 55 | head_ptr <= head_ptr + 4'h1; 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /BMP_display/instr_mem.v: -------------------------------------------------------------------------------- 1 | module IM(clk,addr,rd_en,instr); 2 | 3 | input clk; 4 | input [13:0] addr; 5 | input rd_en; // asserted when instruction read desired 6 | 7 | output reg [15:0] instr; // output of insturction memory 8 | 9 | reg [15:0]instr_mem[0:16383]; // 16K*16 instruction memory 10 | 11 | /////////////////////////////////// 12 | // Memory is flopped on negedge // 13 | ///////////////////////////////// 14 | always @(negedge clk) 15 | if (rd_en) 16 | instr <= instr_mem[addr]; 17 | 18 | initial begin 19 | $readmemh("BMP.hex",instr_mem); 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /BMP_display/madisonCapitol.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/BMP_display/madisonCapitol.bmp -------------------------------------------------------------------------------- /BMP_display/prgm_cntr.v: -------------------------------------------------------------------------------- 1 | module pc(clk,rst_n,stall_IM_ID,dst_ID_EX, 2 | pc,pc_ID_EX,flow_change_ID_EX,pc_EX_DM); 3 | ////////////////////////////////////////////////////////////////////////////\ 4 | // This module implements the program counter logic. It normally increments \\ 5 | // the PC by 1, but when a branch is taken will add the 9-bit immediate \\ 6 | // field to the PC+1. In case of a jmp_imm it will add the 12-bit immediate // 7 | // field to the PC+1. In the case of a jmp_reg it will use the register // 8 | // port zero (p0) register access as the new value of the PC. It also // 9 | // provides PC+1 as nxt_pc for JAL instructions. // 10 | /////////////////////////////////////////////////////////////////////////// 11 | input clk,rst_n; 12 | input flow_change_ID_EX; // asserted from branch boolean on jump or taken branch 13 | input stall_IM_ID; // asserted if we need to stall the pipe 14 | input [15:0] dst_ID_EX; // branch target address comes in on this bus 15 | 16 | output [15:0] pc; // the PC, forms address to instruction memory 17 | output reg [15:0] pc_ID_EX; // needed in EX stage for Branch instruction 18 | output reg [15:0] pc_EX_DM; // needed in dst_mux for JAL instruction 19 | 20 | reg [15:0] pc,pc_IM_ID; 21 | 22 | wire [15:0] nxt_pc; 23 | 24 | ///////////////////////////////////// 25 | // implement incrementer for PC+1 // 26 | /////////////////////////////////// 27 | assign nxt_pc = pc + 1; 28 | 29 | //////////////////////////////// 30 | // Implement the PC register // 31 | ////////////////////////////// 32 | always @(posedge clk, negedge rst_n) 33 | if (!rst_n) 34 | pc <= 16'h0000; 35 | else if (!stall_IM_ID) // all stalls stall the PC 36 | if (flow_change_ID_EX) 37 | pc <= dst_ID_EX; 38 | else 39 | pc <= nxt_pc; 40 | 41 | //////////////////////////////////////////////// 42 | // Implement the PC pipelined register IM_ID // 43 | ////////////////////////////////////////////// 44 | always @(posedge clk) 45 | if (!stall_IM_ID) 46 | pc_IM_ID <= nxt_pc; // pipeline PC points to next instruction 47 | 48 | //////////////////////////////////////////////// 49 | // Implement the PC pipelined register ID_EX // 50 | ////////////////////////////////////////////// 51 | always @(posedge clk) 52 | pc_ID_EX <= pc_IM_ID; // pipeline it down to EX stage for jumps 53 | 54 | //////////////////////////////////////////////// 55 | // Implement the PC pipelined register EX_DM // 56 | ////////////////////////////////////////////// 57 | always @(posedge clk) 58 | pc_EX_DM <= pc_ID_EX; // pipeline it down to DM stage for saved register for JAL 59 | 60 | endmodule -------------------------------------------------------------------------------- /BMP_display/report_JQ_HZ_HQ_QL.txt: -------------------------------------------------------------------------------- 1 | TEAM CONTRIBUTIONS 2 | 3 | Justin Qiao: Wrote top-level, reviewed all modifications with Qikun. 4 | Harry Zhao: Packed and decoded control logic of PlaceBMP.sv, tested the asm code with Haining. 5 | Qikun Liu: Generated 3rd image, integrated it into PlaceBMP.sv, wrote all comments with Harry. 6 | Haining Qiu: Wrote assembly code, designd the control signal with Justin. 7 | -------------------------------------------------------------------------------- /BMP_display/rf.v: -------------------------------------------------------------------------------- 1 | module rf(clk,p0_addr,p1_addr,p0,p1,re0,re1,dst_addr,dst,we,hlt); 2 | ////////////////////////////////////////////////////////////////// 3 | // Triple ported register file. Two read ports (p0 & p1), and // 4 | // one write port (dst). Data is written on clock high, and // 5 | // read on clock low ////////////////////////////////////////// 6 | ////////////////////// 7 | 8 | input clk; 9 | input [3:0] p0_addr, p1_addr; // two read port addresses 10 | input re0,re1; // read enables (power not functionality) 11 | input [3:0] dst_addr; // write address 12 | input [15:0] dst; // dst bus 13 | input we; // write enable 14 | input hlt; // not a functional input. Used to dump register contents when 15 | // test is halted. (No longer used) 16 | 17 | output [15:0] p0,p1; // output read ports 18 | 19 | wire r0_bypass, r1_bypass; // RF bypass 20 | wire [15:0] p0_raw, p1_raw; // raw read output from SRAM 21 | 22 | ///////////////////////////////////////////////////////////////////// 23 | // Instantiate two dualport memory to create a tripple port rf // 24 | // Always write same data to both sram instance at the same time // 25 | ////////////////////////////////////////////////////////////////// 26 | dualPort16x16 sram0( 27 | .clk(clk), 28 | .we(we), 29 | .re(re0), 30 | .waddr(dst_addr), 31 | .raddr(p0_addr), 32 | .wdata(dst), 33 | .rdata(p0_raw) 34 | ); 35 | dualPort16x16 sram1( 36 | .clk(clk), 37 | .we(we), 38 | .re(re1), 39 | .waddr(dst_addr), 40 | .raddr(p1_addr), 41 | .wdata(dst), 42 | .rdata(p1_raw) 43 | ); 44 | 45 | // Bypass if any read register is the same as the write register and both re and we are high 46 | assign r0_bypass = ~|(p0_addr ^ dst_addr) & re0 & we; 47 | assign r1_bypass = ~|(p1_addr ^ dst_addr) & re1 & we; 48 | 49 | // R0 always stay at 16'h0000 50 | assign p0 = ~|p0_addr ? 16'h0000 : (r0_bypass ? dst : p0_raw); 51 | assign p1 = ~|p1_addr ? 16'h0000 : (r1_bypass ? dst : p1_raw); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /BMP_display/rst_synch.v: -------------------------------------------------------------------------------- 1 | module rst_synch(clk,RST_n,pll_locked,rst_n); 2 | 3 | input clk; // 50MHz clock 4 | input RST_n; // non synched reset from push button 5 | input pll_locked; // don't deassert reset till PLL is locked 6 | output reg rst_n; // synched on deassert to negedge of clock 7 | 8 | reg q1; 9 | 10 | //////////////////////////////////////////////// 11 | // rst_n is asserted asynch, but deasserted // 12 | // syncronized to negedge clock. Two flops // 13 | // are used for metastability purposes. // 14 | //////////////////////////////////////////// 15 | always @(negedge clk, negedge RST_n) 16 | if (!RST_n) 17 | begin 18 | q1 <= 1'b0; 19 | rst_n <= 1'b0; 20 | end 21 | else 22 | begin 23 | q1 <= pll_locked; 24 | rst_n <= q1; 25 | end 26 | 27 | endmodule -------------------------------------------------------------------------------- /BMP_display/videoMem.sv: -------------------------------------------------------------------------------- 1 | module videoMem(clk,we,waddr,wdata,raddr,rdata); 2 | 3 | input clk; 4 | input we; 5 | input [18:0] waddr; 6 | input [8:0] wdata; 7 | input [18:0] raddr; // although we only need 18 bits for our memory, the 19th bit is still needed for the rdata mux 8 | output reg [8:0] rdata; 9 | 10 | // we cutted the provided videoMem into half of the original size 11 | // to make the compiler happy. The FPGA board does not have enough 12 | // memory for this. 13 | reg [8:0]mem[0:153599]; 14 | 15 | reg [8:0] rdata_raw; 16 | 17 | // we fill the lower half of the screen with 0x1FF, white. 18 | assign rdata = raddr < 19'h25800 ? rdata_raw : 9'h1FF; // 19'h25800 == 153600 19 | 20 | always @(posedge clk) begin 21 | if (we && waddr<153600) 22 | mem[waddr] <= wdata; 23 | rdata_raw <= mem[raddr[17:0]]; 24 | end 25 | 26 | endmodule -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/DE1_SoC_CAMERA.qpf: -------------------------------------------------------------------------------- 1 | DATE = "Thu Jul 11 11:26:45 2013" 2 | QUARTUS_VERSION = "13" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "DE1_SoC_CAMERA" 7 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/RAW2GRAY.v: -------------------------------------------------------------------------------- 1 | module RAW2GRAY(oGrey, 2 | oDVAL, 3 | iX_Cont, 4 | iY_Cont, 5 | iDATA, 6 | iDVAL, 7 | iCLK, 8 | iRST, 9 | oEdge 10 | ); 11 | 12 | input [10:0] iX_Cont; 13 | input [10:0] iY_Cont; 14 | input [11:0] iDATA; 15 | input iDVAL; 16 | input iCLK; 17 | input iRST; 18 | output [11:0] oGrey; 19 | output oDVAL; 20 | output oEdge; 21 | wire [11:0] mDATA_0; 22 | wire [11:0] mDATA_1; 23 | wire [12:0] mDATA_sum; 24 | reg [12:0] mDATA_d; 25 | reg [13:0] mCCD_G; 26 | reg mDVAL; 27 | reg mEdge; 28 | 29 | assign oGrey = mCCD_G[13:2]; 30 | assign oDVAL = mDVAL; 31 | assign oEdge = mEdge; 32 | 33 | assign mDATA_sum = (mDATA_0+mDATA_1); 34 | 35 | Line_Buffer1 u0 ( .clken(iDVAL), 36 | .clock(iCLK), 37 | .shiftin(iDATA), 38 | .taps0x(mDATA_1), 39 | .taps1x(mDATA_0) ); 40 | 41 | always@(posedge iCLK or negedge iRST) 42 | begin 43 | if(!iRST) 44 | begin 45 | mCCD_G <= 0; 46 | mDATA_d <= 0; 47 | mDVAL <= 0; 48 | end 49 | else 50 | begin 51 | mDATA_d <= mDATA_sum; 52 | mDVAL <= {iY_Cont[0]|iX_Cont[0]} ? 1'b0 : iDVAL; 53 | mEdge <= (iY_Cont==0||iX_Cont==0||iY_Cont==11'd479||iX_Cont==11'd639); 54 | mCCD_G <= mDATA_sum+mDATA_d; 55 | end 56 | end 57 | 58 | endmodule 59 | 60 | 61 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/Sdram_Control/Sdram_Params.h: -------------------------------------------------------------------------------- 1 | // Address Space Parameters 2 | 3 | `define ROWSTART 8 4 | `define ROWSIZE 12 5 | `define COLSTART 0 6 | `define COLSIZE 8 7 | `define BANKSTART 20 8 | `define BANKSIZE 2 9 | 10 | // Address and Data Bus Sizes 11 | 12 | `define ASIZE 23 // total address width of the SDRAM 13 | `define DSIZE 16 // Width of data bus to SDRAMS 14 | 15 | 16 | //parameter INIT_PER = 100; // For Simulation 17 | 18 | // Controller Parameter 19 | //////////// 133 MHz /////////////// 20 | /* 21 | parameter INIT_PER = 32000; 22 | parameter REF_PER = 1536; 23 | parameter SC_CL = 3; 24 | parameter SC_RCD = 3; 25 | parameter SC_RRD = 7; 26 | parameter SC_PM = 1; 27 | parameter SC_BL = 1; 28 | */ 29 | /////////////////////////////////////// 30 | //////////// 100 MHz /////////////// 31 | parameter INIT_PER = 24000; 32 | parameter REF_PER = 1024; 33 | parameter SC_CL = 3; 34 | parameter SC_RCD = 3; 35 | parameter SC_RRD = 7; 36 | parameter SC_PM = 1; 37 | parameter SC_BL = 1; 38 | /////////////////////////////////////// 39 | //////////// 50 MHz /////////////// 40 | /* 41 | parameter INIT_PER = 12000; 42 | parameter REF_PER = 512; 43 | parameter SC_CL = 3; 44 | parameter SC_RCD = 3; 45 | parameter SC_RRD = 7; 46 | parameter SC_PM = 1; 47 | parameter SC_BL = 1; 48 | */ 49 | /////////////////////////////////////// 50 | 51 | // SDRAM Parameter 52 | parameter SDR_BL = (SC_PM == 1) ? 3'b111 : 53 | (SC_BL == 1) ? 3'b000 : 54 | (SC_BL == 2) ? 3'b001 : 55 | (SC_BL == 4) ? 3'b010 : 3'b011; 56 | parameter SDR_BT = 1'b0; // 1'b0 : Sequential 1'b1 : Interteave 57 | parameter SDR_CL = (SC_CL == 2) ? 3'b10 : 3'b11; -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/Sdram_Control/Sdram_RD_FIFO.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "FIFO" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Sdram_RD_FIFO.v"] 5 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/Sdram_Control/Sdram_WR_FIFO.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "FIFO" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Sdram_WR_FIFO.v"] 5 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/Line_Buffer1.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "Shift register (RAM-based)" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Line_Buffer1.v"] 5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "Line_Buffer1.bsf"] 6 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll.cmp: -------------------------------------------------------------------------------- 1 | component sdram_pll is 2 | port ( 3 | refclk : in std_logic := 'X'; -- clk 4 | rst : in std_logic := 'X'; -- reset 5 | outclk_0 : out std_logic; -- clk 6 | outclk_1 : out std_logic; -- clk 7 | outclk_2 : out std_logic; -- clk 8 | outclk_3 : out std_logic -- clk 9 | ); 10 | end component sdram_pll; 11 | 12 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll.sip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "sdram_pll" -library "lib_sdram_pll" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "sdram_pll" -library "lib_sdram_pll" -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -entity "sdram_pll" -library "lib_sdram_pll" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "lib_sdram_pll" -name SPD_FILE [file join $::quartus(sip_path) "sdram_pll.spd"] 5 | 6 | set_global_assignment -library "lib_sdram_pll" -name MISC_FILE [file join $::quartus(sip_path) "sdram_pll_sim/sdram_pll.vo"] 7 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll.spd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll/sdram_pll_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*sdram_pll_0002*|altera_pll:altera_pll_i*|*" 2 | 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*sdram_pll_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*sdram_pll_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll_sim.f: -------------------------------------------------------------------------------- 1 | sdram_pll_sim/sdram_pll.vo 2 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll_sim/cadence/cds.lib: -------------------------------------------------------------------------------- 1 | 2 | DEFINE std $CDS_ROOT/tools/inca/files/STD/ 3 | DEFINE synopsys $CDS_ROOT/tools/inca/files/SYNOPSYS/ 4 | DEFINE ieee $CDS_ROOT/tools/inca/files/IEEE/ 5 | DEFINE ambit $CDS_ROOT/tools/inca/files/AMBIT/ 6 | DEFINE vital_memory $CDS_ROOT/tools/inca/files/VITAL_MEMORY/ 7 | DEFINE ncutils $CDS_ROOT/tools/inca/files/NCUTILS/ 8 | DEFINE ncinternal $CDS_ROOT/tools/inca/files/NCINTERNAL/ 9 | DEFINE ncmodels $CDS_ROOT/tools/inca/files/NCMODELS/ 10 | DEFINE cds_assertions $CDS_ROOT/tools/inca/files/CDS_ASSERTIONS/ 11 | DEFINE work ./libraries/work/ 12 | DEFINE altera_ver ./libraries/altera_ver/ 13 | DEFINE lpm_ver ./libraries/lpm_ver/ 14 | DEFINE sgate_ver ./libraries/sgate_ver/ 15 | DEFINE altera_mf_ver ./libraries/altera_mf_ver/ 16 | DEFINE altera_lnsim_ver ./libraries/altera_lnsim_ver/ 17 | DEFINE cyclonev_ver ./libraries/cyclonev_ver/ 18 | DEFINE cyclonev_hssi_ver ./libraries/cyclonev_hssi_ver/ 19 | DEFINE cyclonev_pcie_hip_ver ./libraries/cyclonev_pcie_hip_ver/ 20 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll_sim/cadence/hdl.var: -------------------------------------------------------------------------------- 1 | 2 | DEFINE WORK work 3 | -------------------------------------------------------------------------------- /DE1_SoC_CAMERA_Sol/v/sdram_pll_sim/synopsys/vcsmx/synopsys_sim.setup: -------------------------------------------------------------------------------- 1 | 2 | WORK > DEFAULT 3 | DEFAULT: ./libraries/work/ 4 | work: ./libraries/work/ 5 | altera_ver: ./libraries/altera_ver/ 6 | lpm_ver: ./libraries/lpm_ver/ 7 | sgate_ver: ./libraries/sgate_ver/ 8 | altera_mf_ver: ./libraries/altera_mf_ver/ 9 | altera_lnsim_ver: ./libraries/altera_lnsim_ver/ 10 | cyclonev_ver: ./libraries/cyclonev_ver/ 11 | cyclonev_hssi_ver: ./libraries/cyclonev_hssi_ver/ 12 | cyclonev_pcie_hip_ver: ./libraries/cyclonev_pcie_hip_ver/ 13 | LIBRARY_SCAN = TRUE 14 | -------------------------------------------------------------------------------- /ECE554_Final_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/ECE554_Final_Report.pdf -------------------------------------------------------------------------------- /FPGA_Implementation_of_CNN_Handwritten_Character_Recognition.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/FPGA_Implementation_of_CNN_Handwritten_Character_Recognition.zip -------------------------------------------------------------------------------- /Final_Presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Final_Presentation.pptx -------------------------------------------------------------------------------- /MiniLab0/Documentation/S2014_552_Project_description.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/MiniLab0/Documentation/S2014_552_Project_description.pdf -------------------------------------------------------------------------------- /MiniLab0/Documentation/WISC-S14 ISA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/MiniLab0/Documentation/WISC-S14 ISA.pdf -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/BasicOpCodes1.asm: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # This test focus on Register Register, LLB, LHB, and Shifts # 3 | ############################################################## 4 | LLB R1, 0x55 5 | LLB R2, 0x33 6 | ADD R3, R2, R1 # (should be 0x88) 7 | SUB R4, R1, R2 # (should be 0x22) 8 | ADD R14, R3, R4 # (should be 0xAA in R14) 9 | LLB R13, 0xAA # R13 will contain 0xFFAA (sign extension) 10 | LHB R13, 0x00 # R13 will now contain 0x00AA 11 | SUB R0, R14, R13 # (performing a compare) 12 | B NEQ, FAIL 13 | LLB R5, 0x77 14 | AND R6, R5, R2 # (should be 0x33) 15 | NOR R7, R3, R2 # (should be 0xFF44) 16 | LHB R7, 0x00 # R7 will now contain 0x0044 17 | ADD R8, R0, R0 # R8 = 0x00 18 | LLB R2, 0x01 # R2 = 1 19 | AGN: ADD R8, R8, R2 # R8 = R8 + 1 20 | SUB R7, R7, R4 # R7 = R7 - 0x22 21 | B NEQ, AGN # Will loop twice 22 | SUB R0, R8, R2 # compare R8 to 1 23 | B LTE, FAIL # R8 should equal 2 24 | LLB R9, 0xAA # should contain 0xFFAA (sign extended) 25 | LLB R10, 0x56 26 | ADD R11, R9, R10 # should add to 0x0000 27 | B NEQ, FAIL 28 | LLB R12, 0xAB # R12 = 0xFFAB 29 | LHB R12, 0x34 # R12 = 0x34AB 30 | LLB R13, 0x55 # R13 = 0x0055 31 | LHB R13, 0x7B # R13 = 0x7B55 32 | ADD R14, R13, R12 # should saturate to 0x7FFF with overflow 33 | B OVFL, CONT # branch to continue test 34 | B UNCOND, FAIL # else we jump to fail routine 35 | CONT: LLB R13, 0xFF # R13 = 0xFFFF 36 | LHB R13, 0x7F # R13 = 0x7FFF 37 | SUB R0, R13, R14 # compare 38 | B NEQ, FAIL 39 | SLL R13, R12,0x02 # R13 should contain 0xD2AC 40 | SRA R12, R13,4 # R12 should contain 0xFD2A 41 | SLL R13, R13,3 # R13 should contain 0x9560 42 | SLL R12, R12,7 # R12 should contain 0x9500 43 | ADD R14, R12, R13 # R14 should sat to 0x8000 44 | B OVFL, CONT2 # overflow should be set 45 | B UNCOND, FAIL 46 | CONT2: LLB R9, 0x00 47 | LHB R9, 0x80 48 | SUB R0, R14, R9 # compare R14 to 0x8000 49 | B NEQ, FAIL 50 | SRL R14, R14, 8 # R14 should contain 0x0080 51 | LLB R9, 0x80 52 | LHB R9, 0x00 53 | SUB R0, R14, R9 54 | B NEQ, FAIL 55 | 56 | 57 | PASS: LLB R1, 0xAA # R1 will contain 0xFFAA 58 | LHB R1, 0xAA # R1 will contain 0xAAAA (indicated pass) 59 | HLT 60 | FAIL: LLB R1, 0xFF # R1 will contain 0xFFFF (indicates failure) 61 | HLT -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/BasicOpCodes2.asm: -------------------------------------------------------------------------------- 1 | ##################################### 2 | # This test focus on LW/SW and ADDZ # 3 | ##################################### 4 | LLB R6, 0x33 # R6 contains 0x0033 5 | LLB R10, 0x56 # R10 contains 0x0056 6 | LLB R8, 0x02 # R8 contains 0x0002 7 | LLB R2, 0x40 8 | ADD R14, R2, R2 # R14 contains 0x80 9 | LLB R12, 0x00 10 | LHB R12, 0x95 # R12 contains 0x9500 11 | LLB R13, 0x60 12 | LHB R13, 0x95 # R13 contains 0x9560 13 | 14 | ############################## 15 | # Now for some LW/SW testing # 16 | ############################## 17 | SW R12, R14,0x2 # storing 0x9500 at location 0x0082 18 | SW R13, R14,0x3 # storing 0x9560 at location 0x0083 19 | LLB R1, 0x04 # R1 should have 4 20 | ADD R2, R1, R14 # R2 should now have 0x0084 21 | LW R3, R2, 0xE # should be loading R3 with location 0x0082 (9500) 22 | SUB R0, R3, R12 23 | B NEQ, FAIL 24 | LW R4, R2, 0xF # should be loading R4 with location 0x0083 (9560) 25 | SUB R0, R4, R13 26 | B NEQ, FAIL 27 | ################# 28 | # ADDZ testing # 29 | ################# 30 | ADDZ R5, R6, R10 # zero flag should last be set so R5 = 0x0056+0x0033 31 | LLB R7, 0x89 32 | LHB R7, 0x00 33 | SUB R0, R7, R5 34 | B NEQ, FAIL 35 | ADD R0, R6, R6 # this add should clear zero flag 36 | ADDZ R8, R10, R10 # would be performing 0x0056 + 0x0056, however R8 should stay 0x0002 37 | LLB R9, 0x02 38 | SUB R0, R8, R9 39 | B NEQ, FAIL 40 | 41 | PASS: LLB R1, 0xAA # R1 will contain 0xFFAA 42 | LHB R1, 0xAA # R1 will contain 0xAAAA (indicated pass) 43 | HLT 44 | 45 | FAIL: LLB R1, 0xFF # R1 will contain 0xFFFF (indicates failure) 46 | HLT -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/BasicOpCodes3.asm: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | # This test focuses more on control instructions (branches) # 3 | ############################################################# 4 | LLB R1, 0x55 5 | LLB R2, 0x33 6 | ADD R3, R2, R1 # (should be 0x88) 7 | B NEQ, CONT1 # NEQ taken branch 8 | B UNCOND, FAIL 9 | CONT1: SUB R0, R2, R2 # will result in zero 10 | B NEQ, FAIL # NEQ not taken branch 11 | B EQ, CONT2 # taken EQ branch 12 | B UNCOND, FAIL 13 | CONT2: SUB R0, R1, R2 # 55 - 33 14 | B EQ, FAIL # not taken EQ branch 15 | B GT, CONT3 # Taken GT branch 16 | B UNCOND, FAIL 17 | CONT3: SUB R0, R1, R1 # 55 - 55 18 | B GT, FAIL # not taken GT branch 19 | B LT, FAIL # not taken LT branch 20 | SUB R0, R2, R1 # 33 - 55 21 | B LT, CONT4 # taken LT branch 22 | B UNCOND, FAIL 23 | CONT4: SUB R0, R3, R3 # 88 - 88 24 | B GTE, CONT5 # taken GTE (=) 25 | B UNCOND, FAIL 26 | CONT5: SUB R0, R1, R3 # 55 - 88 27 | B GTE, FAIL # not taken GTE 28 | SUB R0, R3, R1 # 88 - 55 29 | B GTE, CONT6 # taken GTE (>) 30 | B UNCOND, FAIL 31 | CONT6: SUB R0, R1, R3 # 55 - 88 32 | B LTE, CONT7 # taken LTE (<) 33 | B UNCOND, FAIL 34 | CONT7: SUB R0, R1, R1 # 55 - 55 35 | B LTE, CONT8 # taken LTE (=) 36 | B UNCOND, FAIL 37 | CONT8: SUB R0, R3, R1 # 88 - 55 38 | B LTE, FAIL # not taken LTE 39 | LHB R1, 0x7F # R1 now contains 0x7F55 40 | LHB R3, 0x70 # R3 now contains 0x7088 41 | ADD R0, R1, R3 # positive overflow 42 | B OVFL, CONT9 # taken OVFL 43 | B UNCOND, FAIL 44 | CONT9: SUB R0, R3, R1 # no overflow 45 | B OVFL, FAIL # not taken OVFL 46 | 47 | PASS: LLB R1, 0xAA # R1 will contain 0xFFAA 48 | LHB R1, 0xAA # R1 will contain 0xAAAA (indicated pass) 49 | HLT 50 | ADD R0, R0, R0 # Nop in case their halt instruction does not stop in time 51 | 52 | FAIL: LLB R1, 0xFF # R1 will contain 0xFFFF (indicates failure) 53 | HLT 54 | 55 | -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/BasicOpCodes4.asm: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | # This test focuses more on control instructions (branches) # 3 | ############################################################# 4 | 5 | ################################# 6 | # This section focuses on jumps # 7 | ################################# 8 | LLB R1, 0x05 # R1 contains address of CONT1 9 | JR R1 # Jump to CONT1 10 | B UNCOND, FAIL 11 | ADD R0, R0, R0 12 | ADD R0, R0, R0 13 | CONT1: JAL FUNC # jump to function 14 | LLB R4, 0x57 15 | SUB R0, R3, R4 16 | B EQ, PASS 17 | 18 | FAIL: LLB R1, 0xFF # R1 will contain 0xFFFF (indicates failure) 19 | HLT 20 | 21 | PASS: LLB R1, 0xAA # R1 will contain 0xFFAA 22 | LHB R1, 0xAA # R1 will contain 0xAAAA (indicated pass) 23 | HLT 24 | 25 | FUNC: LLB R3, 0x57 26 | JR R15 # return 27 | -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/Branchtown.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0x01 2 | LHB R1, 0x00 3 | LLB R2, 0x22 4 | LHB R2, 0x22 5 | LLB R3, 0x33 6 | LHB R3, 0x33 7 | LLB R4, 0x44 8 | LHB R4, 0x44 9 | LLB R5, 0x55 10 | LHB R5, 0x55 11 | LLB R6, 0x66 12 | LHB R6, 0x66 13 | LLB R7, 0x77 14 | LHB R7, 0x77 15 | LLB R8, 0x88 16 | LHB R8, 0x88 17 | LLB R9, 0x99 18 | LHB R9, 0x99 19 | LLB R10, 0xaa 20 | LHB R10, 0xaa 21 | LLB R11, 0xbb 22 | LHB R11, 0xbb 23 | LLB R12, 0xcc 24 | LHB R12, 0xcc 25 | LLB R13, 0xdd 26 | LHB R13, 0xdd 27 | LLB R14, 0xee 28 | LHB R14, 0xee 29 | LLB R15, 0xff 30 | LHB R15, 0xff 31 | jal r15change 32 | hlt //r15change adds 1 to R15, skips this halt 33 | add R0, R15, R1 34 | add R15, R0, R15 35 | add R1, R1, R1 36 | B GT, hop 37 | hlt 38 | hop: 39 | SW R14, R8, 3 40 | add R8, R8, R1 41 | LW R13, R8, 1 42 | add R11, R0, R13 43 | B NEQ, hop2 44 | add R13, R11, R11 45 | hop2: 46 | jal jalswap 47 | add R1, R12, R0 //should happen 48 | hlt //corect halt location 49 | 50 | r15change: 51 | add R15, R15, R1 52 | jr R15 53 | hlt 54 | jalret: 55 | jr R15 56 | jalswap: 57 | sw R15, R12, 7 58 | lw R2, R12, 7 59 | jr R2 -------------------------------------------------------------------------------- /MiniLab0/ExampleASM_and_Assembler/test3.asm: -------------------------------------------------------------------------------- 1 | llb R1,0x04 2 | Add R2,R1,R1 3 | llb R3,0x7f 4 | sw R2,R3,0 5 | lw R4,R3,0 6 | jr R4 7 | hlt 8 | add R5,R4,R4 9 | JAl d1 10 | d1: 11 | B eq,Dead 12 | addz R6,R0,R0 13 | B neq,Dead 14 | addz R7,R4,R4 15 | b eq,Dead 16 | and R8,R7,R3 17 | sll R9,R8,2 18 | SRA R10,R9,2 19 | SRL R11,R10,3 20 | nor R12,R11,R10 21 | sw R12,R3,0 22 | JAL d2 23 | hlt 24 | 25 | Dead: 26 | llb R15,0xef 27 | lhb R15,0xbe 28 | hlt 29 | 30 | d2: 31 | lw R15,R3,0 32 | jr R15 33 | hlt -------------------------------------------------------------------------------- /MiniLab0/MiniLab0.sv: -------------------------------------------------------------------------------- 1 | module MiniLab0(clk,KEY0,LEDR,SW); 2 | 3 | input clk; 4 | input KEY0; // master reset button 5 | input [9:0] SW; // 10 switches, external address = 0xC001 6 | output reg [9:0] LEDR; // 10 LEDs, external address = 0xC000 7 | 8 | wire rst_n; // synchronized active low reset 9 | wire [15:0] addr; // dst_EX_DM, result from ALU 10 | wire [15:0] rdata; // exteral data input from the switches, 16'hDEAD if addr != 16'hC001 11 | wire [15:0] wdata; // data from cpu that will reflect on LEDs if addr == 16'hC000 during write 12 | wire update_LED; // update LED status if addr == 16'hC000 and we is set 13 | 14 | // push button input synchronization 15 | rst_synch irst_synch( 16 | .RST_n(KEY0), 17 | .clk(clk), 18 | .rst_n(rst_n) 19 | ); 20 | 21 | // iDUT 22 | cpu icpu( 23 | .clk(clk), 24 | .rst_n(rst_n), 25 | .rdata(rdata), 26 | .addr(addr), 27 | .re(re), 28 | .we(we), 29 | .wdata(wdata) 30 | ); 31 | 32 | assign rdata = ((addr == 16'hC001) & re) ? {6'b000000, SW} : 16'hDEAD; // If external addr invalid, put 0xDEAD on data line 33 | 34 | assign update_LED = (addr == 16'hC000) & we; // make testbench more straight forward 35 | 36 | // Considering LED as a "memory", so picked negedge trigged flops 37 | always @(negedge clk, negedge rst_n) 38 | if(!rst_n) 39 | LEDR <= 10'h000; // LED output default to all OFF 40 | else if (update_LED) 41 | LEDR <= wdata[9:0]; // data is 16 bit, but only have 10 LEDs, use lower bits 42 | 43 | endmodule -------------------------------------------------------------------------------- /MiniLab0/MiniLab0_tb.sv: -------------------------------------------------------------------------------- 1 | module MiniLab0_tb(); 2 | 3 | logic clk; 4 | logic KEY0; 5 | logic [9:0] SW; 6 | logic [9:0] LEDR; 7 | logic halt; 8 | 9 | assign halt = iDUT.icpu.hlt_DM_WB; // extract hlt signal from icpu 10 | 11 | MiniLab0 iDUT( 12 | .clk(clk), 13 | .KEY0(KEY0), 14 | .LEDR(LEDR), 15 | .SW(SW) 16 | ); 17 | 18 | initial begin 19 | clk = 1'b0; 20 | KEY0 = 1'b0; 21 | @(posedge clk); 22 | @(negedge clk) KEY0 = 1'b1; 23 | 24 | // run random test 30 times 25 | for(int i = 0; i < 30; i++) begin 26 | @(negedge clk) SW = $random; // randomly choose a SW pattern 27 | if(SW === 10'b11_1111_1111) // if, unfortunately, hit all 1s, break out to test halting feature in advance 28 | break; 29 | @(negedge iDUT.update_LED) // wait until LEDs are updated 30 | if(LEDR !== SW) begin // check if LED reflects the state of SW 31 | $display("ERROR: LED failed to reflect SW state!"); 32 | $stop(); 33 | end 34 | end 35 | 36 | // test halting feature (when all SWs are ON, program should halt for good) 37 | @(negedge clk) SW = 10'b11_1111_1111; 38 | wait4sig(halt, 20); // assert timeout error if do not see halt in 20 cycles after all SW pulled up 39 | repeat(3)@(posedge clk); // just to get a prettier waveform 40 | 41 | $display("ALL TESTS PASSED!!!"); 42 | $stop(); 43 | end 44 | 45 | // task to check timeouts of waiting the posedge of a given status signal 46 | task automatic wait4sig(ref sig, input int clks2wait); 47 | fork 48 | begin: timeout 49 | repeat(clks2wait) @(posedge clk); 50 | $display("ERROR: timed out waiting for sig in wait4sig"); 51 | $stop(); 52 | end 53 | begin 54 | @(posedge sig) 55 | disable timeout; 56 | end 57 | join 58 | endtask 59 | 60 | always 61 | #5 clk = ~clk; 62 | 63 | endmodule -------------------------------------------------------------------------------- /MiniLab0/Quartus/MiniLab0.qpf: -------------------------------------------------------------------------------- 1 | DATE = "21:23:40 February 01, 2023" 2 | QUARTUS_VERSION = "15.1.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "MiniLab0" 7 | -------------------------------------------------------------------------------- /MiniLab0/assembly/complex.asm: -------------------------------------------------------------------------------- 1 | ADD R1, R0, R0 2 | LHB R1, 0xC0 # R0 <= 0xC000 3 | LLB R3, 0xFF 4 | LHB R3, 0x03 # R3 <= 0x03FF (meaning all 10 SW are ON) 5 | INPUT: LW R2, R1, 1 # read switch(addr=0xC001) status to R2 6 | SUB R4, R2, R3 # check if all switches are ON 7 | B EQ, EXIT # if all SWs are ON, Halt for good 8 | SW R2, R1, 0 # otherwise, reflect SW status to LEDs 9 | B UNCOND, INPUT # then loop back to read SW 10 | EXIT: HLT # all LEDs but the one corresponding to the last switch pulled up are ON 11 | -------------------------------------------------------------------------------- /MiniLab0/assembly/complex.hex: -------------------------------------------------------------------------------- 1 | @0000 0100 // ADD R1, R0, R0 2 | @0001 A1C0 // LHB R1, 0xC0 3 | @0002 B3FF // LLB R3, 0xFF 4 | @0003 A303 // LHB R3, 0x03 5 | @0004 8211 // INPUT: LW R2, R1, 1 6 | @0005 2423 // SUB R4, R2, R3 7 | @0006 C202 // B EQ, EXIT 8 | @0007 9210 // SW R2, R1, 0 9 | @0008 CFFB // B UNCOND, INPUT 10 | @0009 F000 // EXIT: HLT -------------------------------------------------------------------------------- /MiniLab0/assembly/demo.hex: -------------------------------------------------------------------------------- 1 | @0000 0100 // ADD R1, R0, R0 2 | @0001 A1C0 // LHB R1, 0xC0 3 | @0002 8211 // LW R2, R1, 1 4 | @0003 9210 // SW R2, R1, 0 5 | @0004 CFFB // B UNCOND, -5 -------------------------------------------------------------------------------- /MiniLab0/assembly/instr.hex: -------------------------------------------------------------------------------- 1 | @0000 B155 // LLB R1, 0x55 2 | @0001 B233 // LLB R2, 0x33 3 | @0002 BA01 // LLB R10, 0x01 4 | @0003 BB01 // LLB R11, 0x01 5 | @0004 0321 // ADD R3, R2, R1 6 | @0005 9323 // SW R3, R2, 0x03 7 | @0006 8423 // LW R4, R2, 0x03 8 | @0007 2043 // SUB R0, R4, R3 9 | @0008 C204 // B EQ, ARND 10 | @0009 0BBA // ADD R11, R11, R10 11 | @000a 0BBA // ADD R11, R11, R10 12 | @000b 0BBA // ADD R11, R11, R10 13 | @000c 0BBA // ADD R11, R11, R10 14 | @000d 20AB // ARND: SUB R0, R10, R11 15 | @000e C202 // B EQ, PASS 16 | @000f B1FF // FAIL: LLB R1, 0xFF 17 | @0010 F000 // HLT 18 | @0011 B1AA // PASS: LLB R1, 0xAA 19 | @0012 A1AA // LHB R1, 0xAA 20 | @0013 F000 // HLT 21 | -------------------------------------------------------------------------------- /MiniLab0/assembly/load_sw_to_led.asm: -------------------------------------------------------------------------------- 1 | ADD R1, R0, R0 2 | LHB R1, 0xC0 3 | RDSW: LW R2, R1, 1 4 | SW R2, R1, 0 5 | B UNCOND, RDSW 6 | -------------------------------------------------------------------------------- /MiniLab0/assembly/load_sw_to_led.hex: -------------------------------------------------------------------------------- 1 | @0000 0100 // ADD R1, R0, R0 2 | @0001 A1C0 // LHB R1, 0xC0 3 | @0002 8211 // RDSW: LW R2, R1, 1 4 | @0003 9210 // SW R2, R1, 0 5 | @0004 CFFD // B UNCOND, RDSW -------------------------------------------------------------------------------- /MiniLab0/br_bool.v: -------------------------------------------------------------------------------- 1 | module br_bool(clk,rst_n,clk_z_ID_EX,clk_nv_ID_EX,br_instr_ID_EX, 2 | jmp_imm_ID_EX,jmp_reg_ID_EX,cc_ID_EX,zr,ov,neg, 3 | zr_EX_DM,flow_change_ID_EX); 4 | 5 | ////////////////////////////////////////////////////// 6 | // determines branch or not based on cc, and flags // 7 | //////////////////////////////////////////////////// 8 | input clk,rst_n; 9 | input clk_z_ID_EX; // from ID, tells us to flop the zero flag 10 | input clk_nv_ID_EX; // from ID, tells us to flop the overflow flag 11 | input br_instr_ID_EX; // from ID, tell us if this is a branch instruction 12 | input jmp_imm_ID_EX; // from ID, tell us this is jump immediate instruction 13 | input jmp_reg_ID_EX; // from ID, tell us this is jump register instruction 14 | input [2:0] cc_ID_EX; // condition code from instr[11:9] 15 | input zr,ov,neg; // flag bits from ALU 16 | 17 | output reg flow_change_ID_EX; // asserted if we should take branch or jumping 18 | output reg zr_EX_DM; // goes to ID for ADDZ 19 | 20 | reg neg_EX_DM,ov_EX_DM; 21 | 22 | ///////////////////////// 23 | // Flop for zero flag // 24 | /////////////////////// 25 | always @(posedge clk, negedge rst_n) 26 | if (!rst_n) 27 | zr_EX_DM <= 0; 28 | else if (clk_z_ID_EX) 29 | zr_EX_DM <= zr; 30 | 31 | 32 | ///////////////////////////////////// 33 | // Flops for negative and ov flag // 34 | /////////////////////////////////// 35 | always @(posedge clk, negedge rst_n) 36 | if (!rst_n) 37 | begin 38 | ov_EX_DM <= 0; 39 | neg_EX_DM <= 0; 40 | end 41 | else if (clk_nv_ID_EX) 42 | begin 43 | ov_EX_DM <= ov; 44 | neg_EX_DM <= neg; 45 | end 46 | 47 | always @(br_instr_ID_EX,cc_ID_EX,zr_EX_DM,ov_EX_DM,neg_EX_DM,jmp_reg_ID_EX,jmp_imm_ID_EX) begin 48 | 49 | flow_change_ID_EX = jmp_imm_ID_EX | jmp_reg_ID_EX; // jumps always change the flow 50 | 51 | if (br_instr_ID_EX) 52 | case (cc_ID_EX) 53 | 3'b000 : flow_change_ID_EX = ~zr_EX_DM; 54 | 3'b001 : flow_change_ID_EX = zr_EX_DM; 55 | 3'b010 : flow_change_ID_EX = ~zr_EX_DM & ~neg_EX_DM; 56 | 3'b011 : flow_change_ID_EX = neg_EX_DM; 57 | 3'b100 : flow_change_ID_EX = zr_EX_DM | (~zr_EX_DM & ~neg_EX_DM); 58 | 3'b101 : flow_change_ID_EX = neg_EX_DM | zr_EX_DM; 59 | 3'b110 : flow_change_ID_EX = ov_EX_DM; 60 | 3'b111 : flow_change_ID_EX = 1; 61 | endcase 62 | end 63 | 64 | endmodule -------------------------------------------------------------------------------- /MiniLab0/common_params.inc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////// 3 | // Create defines for ALU functions // 4 | ///////////////////////////////////// 5 | localparam ADD = 3'b000; 6 | localparam SUB = 3'b001; 7 | localparam AND = 3'b010; 8 | localparam NOR = 3'b011; 9 | localparam SLL = 3'b100; 10 | localparam SRL = 3'b101; 11 | localparam SRA = 3'b110; 12 | localparam LHB = 3'b111; 13 | 14 | ////////////////////////////////////////// 15 | // Create defines for Opcode encodings // 16 | //////////////////////////////////////// 17 | localparam ADDi = 4'b0000; 18 | localparam ADDZi = 4'b0001; 19 | localparam SUBi = 4'b0010; 20 | localparam ANDi = 4'b0011; 21 | localparam NORi = 4'b0100; 22 | localparam SLLi = 4'b0101; 23 | localparam SRLi = 4'b0110; 24 | localparam SRAi = 4'b0111; 25 | localparam LWi = 4'b1000; 26 | localparam SWi = 4'b1001; 27 | localparam LHBi = 4'b1010; 28 | localparam LLBi = 4'b1011; 29 | localparam BRi = 4'b1100; 30 | localparam JALi = 4'b1101; 31 | localparam JRi = 4'b1110; 32 | localparam HLTi = 4'b1111; 33 | 34 | //////////////////////////////// 35 | // Encodings for src0 select // 36 | ////////////////////////////// 37 | localparam RF2SRC0 = 2'b00; 38 | localparam IMM_BR2SRC0 = 2'b01; // 7-bit SE for branch target 39 | localparam IMM_JMP2SRC0 = 2'b10; // 12-bit SE for jump target 40 | localparam IMM2SRC0 = 2'b11; // 4-bit SE Address immediate for LW/SW 41 | 42 | //////////////////////////////// 43 | // Encodings for src1 select // 44 | ////////////////////////////// 45 | localparam RF2SRC1 = 2'b00; 46 | localparam IMM2SRC1 = 2'b01; // 8-bit data immediate for LLB/LHB 47 | localparam NPC2SRC1 = 2'b10; // nxt_pc to src1 for JAL instruction 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /MiniLab0/complex.asm: -------------------------------------------------------------------------------- 1 | ADD R1, R0, R0 2 | LHB R1, 0xC0 # R0 <= 0xC000 3 | LLB R3, 0xFF 4 | LHB R3, 0x03 # R3 <= 0x03FF (meaning all 10 SW are ON) 5 | INPUT: LW R2, R1, 1 # read switch(addr=0xC001) status to R2 6 | SUB R4, R2, R3 # check if all switches are ON 7 | B EQ, EXIT # if all SWs are ON, Halt for good 8 | SW R2, R1, 0 # otherwise, reflect SW status to LEDs 9 | B UNCOND, INPUT # then loop back to read SW 10 | EXIT: HLT # all LEDs but the one corresponding to the last switch pulled up are ON 11 | -------------------------------------------------------------------------------- /MiniLab0/cpu_tb.v: -------------------------------------------------------------------------------- 1 | module cpu_tb(); 2 | 3 | reg clk,rst_n; 4 | 5 | ////////////////////// 6 | // Instantiate CPU // 7 | //////////////////// 8 | cpu iCPU(.clk(clk), .rst_n(rst_n)); 9 | 10 | initial begin 11 | clk = 0; 12 | rst_n = 0; 13 | #2 rst_n = 1; 14 | end 15 | 16 | always 17 | #1 clk = ~clk; 18 | 19 | endmodule -------------------------------------------------------------------------------- /MiniLab0/data_mem.v: -------------------------------------------------------------------------------- 1 | module DM(clk,addr,re,we,wrt_data,rd_data); 2 | 3 | ///////////////////////////////////////////////////////// 4 | // Data memory. Single ported, can read or write but // 5 | // not both in a single cycle. Precharge on clock // 6 | // high, read/write on clock low. // 7 | ///////////////////////////////////////////////////// 8 | input clk; 9 | input [15:0] addr; 10 | input re; // asserted when instruction read desired 11 | input we; // asserted when write desired 12 | input [15:0] wrt_data; // data to be written 13 | 14 | output reg [15:0] rd_data; //output of data memory 15 | 16 | reg [15:0]data_mem[0:8191]; // 8K*16 data memory 17 | 18 | ///////////////////////////////////////// 19 | // Read is synchronous on negedge clk // 20 | /////////////////////////////////////// 21 | always @(negedge clk) 22 | if (re && ~we) 23 | rd_data <= data_mem[addr]; 24 | 25 | ///////////////////////////////////////////////// 26 | // Model write, data is written on clock fall // 27 | /////////////////////////////////////////////// 28 | always @(negedge clk) 29 | if (we && ~re) 30 | data_mem[addr] <= wrt_data; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /MiniLab0/dst_mux.v: -------------------------------------------------------------------------------- 1 | module dst_mux(clk,dm_re_EX_DM,dm_rd_data_EX_DM,pc_EX_DM,dst_EX_DM,rf_w_data_DM_WB,jmp_imm_EX_DM); 2 | //////////////////////////////////////////////////////////////////////// 3 | // Simple 2:1 mux determining if ALU or DM is source for write to RF // 4 | ////////////////////////////////////////////////////////////////////// 5 | input clk; 6 | input dm_re_EX_DM; 7 | input jmp_imm_EX_DM; 8 | input [15:0] dm_rd_data_EX_DM; // input from DM 9 | input [15:0] pc_EX_DM; // from PC for JAL saving to R15 10 | input [15:0] dst_EX_DM; // input from ALU 11 | 12 | output reg[15:0] rf_w_data_DM_WB; // output to be written to RF 13 | 14 | always @(posedge clk) 15 | if (dm_re_EX_DM) 16 | rf_w_data_DM_WB <= dm_rd_data_EX_DM; 17 | else if (jmp_imm_EX_DM) 18 | rf_w_data_DM_WB <= pc_EX_DM; 19 | else 20 | rf_w_data_DM_WB <= dst_EX_DM; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /MiniLab0/dualPort16x16.sv: -------------------------------------------------------------------------------- 1 | module dualPort16x16(clk,we,re,waddr,raddr,wdata,rdata); 2 | 3 | input clk; // system clock 4 | input we; // write enable 5 | input re; // read enable 6 | input [3:0] waddr; // write address 7 | input [3:0] raddr; // read address 8 | input [15:0] wdata; // data to write 9 | output reg [15:0] rdata; // read data output 10 | 11 | reg [15:0] mem [15:0]; // 16 by 16 SRAM block 12 | 13 | // negedge triggered memory 14 | always @(negedge clk) begin 15 | if(we) 16 | mem[waddr] <= wdata; 17 | if(re) 18 | rdata <= mem[raddr]; 19 | end 20 | 21 | endmodule -------------------------------------------------------------------------------- /MiniLab0/instr_mem.v: -------------------------------------------------------------------------------- 1 | module IM(clk,addr,rd_en,instr); 2 | 3 | input clk; 4 | input [15:0] addr; 5 | input rd_en; // asserted when instruction read desired 6 | 7 | output reg [15:0] instr; //output of insturction memory 8 | 9 | reg [15:0]instr_mem[0:16383]; // 16K*16 instruction memory 10 | 11 | /////////////////////////////////// 12 | // Memory is flopped on negedge // 13 | ///////////////////////////////// 14 | always @(negedge clk) 15 | if (rd_en) 16 | instr <= instr_mem[addr]; 17 | 18 | initial begin 19 | $readmemh("C:/Users/13651/Desktop/ECE554/Minilab0/MiniLab0/assembly/complex.hex",instr_mem); 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /MiniLab0/miniproject0_552Proc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/MiniLab0/miniproject0_552Proc.pdf -------------------------------------------------------------------------------- /MiniLab0/report.txt: -------------------------------------------------------------------------------- 1 | Problem 1: 2 | During conversion from latch based memory to FF based memory, 3 | we encountered a problem where the initial rdata is 16'hxxxx 4 | and the rdata feeds back as the wdata. Therefore, it enters a 5 | stage loop where the 16'hxxxx is fed back to rf. 6 | Solution: 7 | We AND bypass logic with both read_enable and write_enable to 8 | ensure that bypass does not happen during initialization stage. 9 | 10 | Problem 2: 11 | The initial block to load memory does not synthesize properly, 12 | so that we could not reset R0 to 0 through the given code. 13 | Solution: 14 | Take out entire inital block and add logic in rf.v to force read 15 | data to 16'h0000 if the corresponding addrss is 4'b0000 at a 16 | rf read operation. 17 | 18 | Problem 3: 19 | We originally have an asm code with a halt instrction in the end, 20 | but we observed that sometimes our program actually looped back 21 | to the beginning due to PC over flow. We were unsure about if the 22 | halt function was broken with that weak asm test. 23 | Solution: 24 | There was a bug in the code, and we fixed that easily. What more 25 | important is, in the asm code, we implemented conditional branches 26 | so that if all switches are ON, the system will halt forever, 27 | otherwise the program will keep looping. This is a good indicator 28 | that our processor handles conditional branch and halt instructions properly. 29 | 30 | Problem 4: 31 | We met a situation where quartus do not think the SRAM block usage 32 | equals to 16K*16+8K*16+16*16*2=393728 bits. 33 | Solution: 34 | We moved rf bypass logic out of the sram module, and quartus coorporated. -------------------------------------------------------------------------------- /MiniLab0/rf.v: -------------------------------------------------------------------------------- 1 | module rf(clk,p0_addr,p1_addr,p0,p1,re0,re1,dst_addr,dst,we,hlt); 2 | ////////////////////////////////////////////////////////////////// 3 | // Triple ported register file. Two read ports (p0 & p1), and // 4 | // one write port (dst). Data is written on clock high, and // 5 | // read on clock low ////////////////////////////////////////// 6 | ////////////////////// 7 | 8 | input clk; 9 | input [3:0] p0_addr, p1_addr; // two read port addresses 10 | input re0,re1; // read enables (power not functionality) 11 | input [3:0] dst_addr; // write address 12 | input [15:0] dst; // dst bus 13 | input we; // write enable 14 | input hlt; // not a functional input. Used to dump register contents when 15 | // test is halted. (No longer used) 16 | 17 | output [15:0] p0,p1; // output read ports 18 | 19 | wire r0_bypass, r1_bypass; // RF bypass 20 | wire [15:0] p0_raw, p1_raw; // raw read output from SRAM 21 | 22 | ///////////////////////////////////////////////////////////////////// 23 | // Instantiate two dualport memory to create a tripple port rf // 24 | // Always write same data to both sram instance at the same time // 25 | ////////////////////////////////////////////////////////////////// 26 | dualPort16x16 sram0( 27 | .clk(clk), 28 | .we(we), 29 | .re(re0), 30 | .waddr(dst_addr), 31 | .raddr(p0_addr), 32 | .wdata(dst), 33 | .rdata(p0_raw) 34 | ); 35 | dualPort16x16 sram1( 36 | .clk(clk), 37 | .we(we), 38 | .re(re1), 39 | .waddr(dst_addr), 40 | .raddr(p1_addr), 41 | .wdata(dst), 42 | .rdata(p1_raw) 43 | ); 44 | 45 | // Bypass if any read register is the same as the write register and both re and we are high 46 | assign r0_bypass = ~|(p0_addr ^ dst_addr) & re0 & we; 47 | assign r1_bypass = ~|(p1_addr ^ dst_addr) & re1 & we; 48 | 49 | // R0 always stay at 16'h0000 50 | assign p0 = ~|p0_addr ? 16'h0000 : (r0_bypass ? dst : p0_raw); 51 | assign p1 = ~|p1_addr ? 16'h0000 : (r1_bypass ? dst : p1_raw); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /MiniLab0/rst_synch.sv: -------------------------------------------------------------------------------- 1 | module rst_synch( 2 | input RST_n, // async push button reset 3 | input clk, // system clock 4 | output reg rst_n // synchronized active low reset 5 | ); 6 | 7 | reg ff1; // buffer register 8 | 9 | // asynch reset when RST_n asserted, other wise, double flop 1'b1 to deassert rst_n on negedge clk 10 | always_ff @(negedge clk, negedge RST_n) 11 | if(!RST_n) begin 12 | ff1 <= 1'b0; 13 | rst_n <= 1'b0; 14 | end 15 | else begin 16 | ff1 <= 1'b1; 17 | rst_n <= ff1; 18 | end 19 | 20 | endmodule -------------------------------------------------------------------------------- /MiniLab1/QSF_FileGeneration.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/MiniLab1/QSF_FileGeneration.pdf -------------------------------------------------------------------------------- /MiniLab1/Quartus/MiniLab1.qpf: -------------------------------------------------------------------------------- 1 | DATE = "17:00:57 February 16, 2023" 2 | QUARTUS_VERSION = "15.1.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "MiniLab1" 7 | -------------------------------------------------------------------------------- /MiniLab1/UART.sv: -------------------------------------------------------------------------------- 1 | module UART(clk,rst_n,RX,TX,rx_rdy,clr_rx_rdy,rx_data,trmt,tx_data,tx_done,baud_div); 2 | 3 | input clk,rst_n; // clock and active low reset 4 | input RX,trmt; // strt_tx tells TX section to transmit tx_data 5 | input clr_rx_rdy; // rx_rdy can be cleared by this or new start bit 6 | input [7:0] tx_data; // byte to transmit 7 | input [12:0] baud_div; // modify baud rate 8 | output TX,rx_rdy,tx_done; // rx_rdy asserted when byte received, 9 | // tx_done asserted when tranmission complete 10 | output [7:0] rx_data; // byte received 11 | 12 | ////////////////////////////// 13 | // Instantiate Transmitter // 14 | //////////////////////////// 15 | UART_tx iTX(.clk(clk), .rst_n(rst_n), .TX(TX), .trmt(trmt), 16 | .tx_data(tx_data), .tx_done(tx_done), .baud_div(baud_div)); 17 | 18 | 19 | /////////////////////////// 20 | // Instantiate Receiver // 21 | ///////////////////////// 22 | UART_rx iRX(.clk(clk), .rst_n(rst_n), .RX(RX), .rdy(rx_rdy), 23 | .clr_rdy(clr_rx_rdy), .rx_data(rx_data), .baud_div(baud_div)); 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /MiniLab1/br_bool.v: -------------------------------------------------------------------------------- 1 | module br_bool(clk,rst_n,clk_z_ID_EX,clk_nv_ID_EX,br_instr_ID_EX, 2 | jmp_imm_ID_EX,jmp_reg_ID_EX,cc_ID_EX,zr,ov,neg, 3 | zr_EX_DM,flow_change_ID_EX); 4 | 5 | ////////////////////////////////////////////////////// 6 | // determines branch or not based on cc, and flags // 7 | //////////////////////////////////////////////////// 8 | input clk,rst_n; 9 | input clk_z_ID_EX; // from ID, tells us to flop the zero flag 10 | input clk_nv_ID_EX; // from ID, tells us to flop the overflow flag 11 | input br_instr_ID_EX; // from ID, tell us if this is a branch instruction 12 | input jmp_imm_ID_EX; // from ID, tell us this is jump immediate instruction 13 | input jmp_reg_ID_EX; // from ID, tell us this is jump register instruction 14 | input [2:0] cc_ID_EX; // condition code from instr[11:9] 15 | input zr,ov,neg; // flag bits from ALU 16 | 17 | output reg flow_change_ID_EX; // asserted if we should take branch or jumping 18 | output reg zr_EX_DM; // goes to ID for ADDZ 19 | 20 | reg neg_EX_DM,ov_EX_DM; 21 | 22 | ///////////////////////// 23 | // Flop for zero flag // 24 | /////////////////////// 25 | always @(posedge clk, negedge rst_n) 26 | if (!rst_n) 27 | zr_EX_DM <= 0; 28 | else if (clk_z_ID_EX) 29 | zr_EX_DM <= zr; 30 | 31 | 32 | ///////////////////////////////////// 33 | // Flops for negative and ov flag // 34 | /////////////////////////////////// 35 | always @(posedge clk, negedge rst_n) 36 | if (!rst_n) 37 | begin 38 | ov_EX_DM <= 0; 39 | neg_EX_DM <= 0; 40 | end 41 | else if (clk_nv_ID_EX) 42 | begin 43 | ov_EX_DM <= ov; 44 | neg_EX_DM <= neg; 45 | end 46 | 47 | always @(br_instr_ID_EX,cc_ID_EX,zr_EX_DM,ov_EX_DM,neg_EX_DM,jmp_reg_ID_EX,jmp_imm_ID_EX) begin 48 | 49 | flow_change_ID_EX = jmp_imm_ID_EX | jmp_reg_ID_EX; // jumps always change the flow 50 | 51 | if (br_instr_ID_EX) 52 | case (cc_ID_EX) 53 | 3'b000 : flow_change_ID_EX = ~zr_EX_DM; 54 | 3'b001 : flow_change_ID_EX = zr_EX_DM; 55 | 3'b010 : flow_change_ID_EX = ~zr_EX_DM & ~neg_EX_DM; 56 | 3'b011 : flow_change_ID_EX = neg_EX_DM; 57 | 3'b100 : flow_change_ID_EX = zr_EX_DM | (~zr_EX_DM & ~neg_EX_DM); 58 | 3'b101 : flow_change_ID_EX = neg_EX_DM | zr_EX_DM; 59 | 3'b110 : flow_change_ID_EX = ov_EX_DM; 60 | 3'b111 : flow_change_ID_EX = 1; 61 | endcase 62 | end 63 | 64 | endmodule -------------------------------------------------------------------------------- /MiniLab1/common_params.inc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////// 3 | // Create defines for ALU functions // 4 | ///////////////////////////////////// 5 | localparam ADD = 3'b000; 6 | localparam SUB = 3'b001; 7 | localparam AND = 3'b010; 8 | localparam NOR = 3'b011; 9 | localparam SLL = 3'b100; 10 | localparam SRL = 3'b101; 11 | localparam SRA = 3'b110; 12 | localparam LHB = 3'b111; 13 | 14 | ////////////////////////////////////////// 15 | // Create defines for Opcode encodings // 16 | //////////////////////////////////////// 17 | localparam ADDi = 4'b0000; 18 | localparam ADDZi = 4'b0001; 19 | localparam SUBi = 4'b0010; 20 | localparam ANDi = 4'b0011; 21 | localparam NORi = 4'b0100; 22 | localparam SLLi = 4'b0101; 23 | localparam SRLi = 4'b0110; 24 | localparam SRAi = 4'b0111; 25 | localparam LWi = 4'b1000; 26 | localparam SWi = 4'b1001; 27 | localparam LHBi = 4'b1010; 28 | localparam LLBi = 4'b1011; 29 | localparam BRi = 4'b1100; 30 | localparam JALi = 4'b1101; 31 | localparam JRi = 4'b1110; 32 | localparam HLTi = 4'b1111; 33 | 34 | //////////////////////////////// 35 | // Encodings for src0 select // 36 | ////////////////////////////// 37 | localparam RF2SRC0 = 2'b00; 38 | localparam IMM_BR2SRC0 = 2'b01; // 7-bit SE for branch target 39 | localparam IMM_JMP2SRC0 = 2'b10; // 12-bit SE for jump target 40 | localparam IMM2SRC0 = 2'b11; // 4-bit SE Address immediate for LW/SW 41 | 42 | //////////////////////////////// 43 | // Encodings for src1 select // 44 | ////////////////////////////// 45 | localparam RF2SRC1 = 2'b00; 46 | localparam IMM2SRC1 = 2'b01; // 8-bit data immediate for LLB/LHB 47 | localparam NPC2SRC1 = 2'b10; // nxt_pc to src1 for JAL instruction 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /MiniLab1/cpu_tb.v: -------------------------------------------------------------------------------- 1 | module cpu_tb(); 2 | 3 | reg clk,rst_n; 4 | 5 | ////////////////////// 6 | // Instantiate CPU // 7 | //////////////////// 8 | cpu iCPU(.clk(clk), .rst_n(rst_n)); 9 | 10 | initial begin 11 | clk = 0; 12 | rst_n = 0; 13 | #2 rst_n = 1; 14 | end 15 | 16 | always 17 | #1 clk = ~clk; 18 | 19 | endmodule -------------------------------------------------------------------------------- /MiniLab1/data_mem.v: -------------------------------------------------------------------------------- 1 | module DM(clk,addr,re,we,wrt_data,rd_data); 2 | 3 | ///////////////////////////////////////////////////////// 4 | // Data memory. Single ported, can read or write but // 5 | // not both in a single cycle. Precharge on clock // 6 | // high, read/write on clock low. // 7 | ///////////////////////////////////////////////////// 8 | input clk; 9 | input [12:0] addr; 10 | input re; // asserted when instruction read desired 11 | input we; // asserted when write desired 12 | input [15:0] wrt_data; // data to be written 13 | 14 | output reg [15:0] rd_data; //output of data memory 15 | 16 | reg [15:0]data_mem[0:8191]; // 8K*16 data memory 17 | 18 | ///////////////////////////////////////// 19 | // Read is synchronous on negedge clk // 20 | /////////////////////////////////////// 21 | always @(negedge clk) 22 | if (re && ~we) 23 | rd_data <= data_mem[addr]; 24 | 25 | ///////////////////////////////////////////////// 26 | // Model write, data is written on clock fall // 27 | /////////////////////////////////////////////// 28 | always @(negedge clk) 29 | if (we && ~re) 30 | data_mem[addr] <= wrt_data; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /MiniLab1/dst_mux.v: -------------------------------------------------------------------------------- 1 | module dst_mux(clk,dm_re_EX_DM,dm_rd_data_EX_DM,pc_EX_DM,dst_EX_DM,rf_w_data_DM_WB,jmp_imm_EX_DM); 2 | //////////////////////////////////////////////////////////////////////// 3 | // Simple 2:1 mux determining if ALU or DM is source for write to RF // 4 | ////////////////////////////////////////////////////////////////////// 5 | input clk; 6 | input dm_re_EX_DM; 7 | input jmp_imm_EX_DM; 8 | input [15:0] dm_rd_data_EX_DM; // input from DM 9 | input [15:0] pc_EX_DM; // from PC for JAL saving to R15 10 | input [15:0] dst_EX_DM; // input from ALU 11 | 12 | output reg[15:0] rf_w_data_DM_WB; // output to be written to RF 13 | 14 | always @(posedge clk) 15 | if (dm_re_EX_DM) 16 | rf_w_data_DM_WB <= dm_rd_data_EX_DM; 17 | else if (jmp_imm_EX_DM) 18 | rf_w_data_DM_WB <= pc_EX_DM; 19 | else 20 | rf_w_data_DM_WB <= dst_EX_DM; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /MiniLab1/dualPort16x16.sv: -------------------------------------------------------------------------------- 1 | module dualPort16x16(clk,we,re,waddr,raddr,wdata,rdata); 2 | 3 | input clk; // system clock 4 | input we; // write enable 5 | input re; // read enable 6 | input [3:0] waddr; // write address 7 | input [3:0] raddr; // read address 8 | input [15:0] wdata; // data to write 9 | output reg [15:0] rdata; // read data output 10 | 11 | reg [15:0] mem [15:0]; // 16 by 16 SRAM block 12 | 13 | // negedge triggered memory 14 | always @(negedge clk) begin 15 | if(we) 16 | mem[waddr] <= wdata; 17 | if(re) 18 | rdata <= mem[raddr]; 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /MiniLab1/fifo.sv: -------------------------------------------------------------------------------- 1 | // A fifo queue that allows read and write at same time 2 | module fifo( 3 | input clk, // 50MHz clk 4 | input rst_n, // asynch active low reset 5 | input w_en, // write enable 6 | input r_en, // read enable 7 | input [7:0] in_data, // data to be stored in queue 8 | output q_full, // indicates queue is full 9 | output q_empty, // indicates queue is empty 10 | output [7:0] out_data, // data to be read in queue 11 | output [3:0] contain_num // Number of used entires in the queue 12 | ); 13 | 14 | ///////////////////////////// 15 | // Declare reg and wires // 16 | /////////////////////////// 17 | reg [3:0] head_ptr, tail_ptr; // Insert into head, pop from tail 18 | reg [7:0] buffer [0:7]; // 8 entry buffer with 8bits wide data 19 | 20 | // When all 8 entries are filled, the lower 3 bits of the pointer will be same, but the highest bit will be different 21 | assign q_full = tail_ptr[2:0] == head_ptr[2:0] && tail_ptr[3] == ~head_ptr[3]; 22 | // When head ptr and tail ptr are same, the queue is empty 23 | assign q_empty = tail_ptr == head_ptr; 24 | // Number of used/filled entry in the queue 25 | assign contain_num = head_ptr - tail_ptr; 26 | 27 | ///////////////////////////////// 28 | // Read data from the buffer // 29 | /////////////////////////////// 30 | assign out_data = buffer[tail_ptr[2:0]]; //Constantly output the data from the tail_ptr 31 | 32 | /////////////////////////////////// 33 | // Write data into the buffer // 34 | ///////////////////////////////// 35 | always_ff @(posedge clk) 36 | if (w_en && !q_full) 37 | buffer[head_ptr[2:0]] <= in_data; 38 | 39 | /////////////////////////////// 40 | // Tail ptr control logic // 41 | ///////////////////////////// 42 | always_ff @(posedge clk, negedge rst_n) 43 | if (!rst_n) 44 | tail_ptr <= 4'h0; 45 | else if (r_en && !q_empty) // Increment tail_ptr when read enabled and queue is not empty 46 | tail_ptr <= tail_ptr + 4'h1; // Increment tail_ptr == pop an entry from the queue 47 | 48 | /////////////////////////////// 49 | // Head ptr control logic // 50 | ///////////////////////////// 51 | always_ff @(posedge clk, negedge rst_n) 52 | if (!rst_n) 53 | head_ptr <= 4'h0; 54 | else if (w_en && !q_full) // Increment head ptr when write enabled and queue is not full 55 | head_ptr <= head_ptr + 4'h1; 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /MiniLab1/instr_mem.v: -------------------------------------------------------------------------------- 1 | module IM(clk,addr,rd_en,instr); 2 | 3 | input clk; 4 | input [13:0] addr; 5 | input rd_en; // asserted when instruction read desired 6 | 7 | output reg [15:0] instr; //output of insturction memory 8 | 9 | reg [15:0]instr_mem[0:16383]; // 16K*16 instruction memory 10 | 11 | /////////////////////////////////// 12 | // Memory is flopped on negedge // 13 | ///////////////////////////////// 14 | always @(negedge clk) 15 | if (rd_en) 16 | instr <= instr_mem[addr]; 17 | 18 | initial begin 19 | $readmemh("C:\\Users\\13651\\Desktop\\ECE554_LAB1\\MiniLab1\\hello_world.hex",instr_mem); 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /MiniLab1/miniproject1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/MiniLab1/miniproject1.pdf -------------------------------------------------------------------------------- /MiniLab1/rf.v: -------------------------------------------------------------------------------- 1 | module rf(clk,p0_addr,p1_addr,p0,p1,re0,re1,dst_addr,dst,we,hlt); 2 | ////////////////////////////////////////////////////////////////// 3 | // Triple ported register file. Two read ports (p0 & p1), and // 4 | // one write port (dst). Data is written on clock high, and // 5 | // read on clock low ////////////////////////////////////////// 6 | ////////////////////// 7 | 8 | input clk; 9 | input [3:0] p0_addr, p1_addr; // two read port addresses 10 | input re0,re1; // read enables (power not functionality) 11 | input [3:0] dst_addr; // write address 12 | input [15:0] dst; // dst bus 13 | input we; // write enable 14 | input hlt; // not a functional input. Used to dump register contents when 15 | // test is halted. (No longer used) 16 | 17 | output [15:0] p0,p1; // output read ports 18 | 19 | wire r0_bypass, r1_bypass; // RF bypass 20 | wire [15:0] p0_raw, p1_raw; // raw read output from SRAM 21 | 22 | ///////////////////////////////////////////////////////////////////// 23 | // Instantiate two dualport memory to create a tripple port rf // 24 | // Always write same data to both sram instance at the same time // 25 | ////////////////////////////////////////////////////////////////// 26 | dualPort16x16 sram0( 27 | .clk(clk), 28 | .we(we), 29 | .re(re0), 30 | .waddr(dst_addr), 31 | .raddr(p0_addr), 32 | .wdata(dst), 33 | .rdata(p0_raw) 34 | ); 35 | dualPort16x16 sram1( 36 | .clk(clk), 37 | .we(we), 38 | .re(re1), 39 | .waddr(dst_addr), 40 | .raddr(p1_addr), 41 | .wdata(dst), 42 | .rdata(p1_raw) 43 | ); 44 | 45 | // Bypass if any read register is the same as the write register and both re and we are high 46 | assign r0_bypass = ~|(p0_addr ^ dst_addr) & re0 & we; 47 | assign r1_bypass = ~|(p1_addr ^ dst_addr) & re1 & we; 48 | 49 | // R0 always stay at 16'h0000 50 | assign p0 = ~|p0_addr ? 16'h0000 : (r0_bypass ? dst : p0_raw); 51 | assign p1 = ~|p1_addr ? 16'h0000 : (r1_bypass ? dst : p1_raw); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /MiniLab1/rst_synch.sv: -------------------------------------------------------------------------------- 1 | module rst_synch( 2 | input RST_n, // async push button reset 3 | input clk, // system clock 4 | output reg rst_n // synchronized active low reset 5 | ); 6 | 7 | reg ff1; // buffer register 8 | 9 | // asynch reset when RST_n asserted, other wise, double flop 1'b1 to deassert rst_n on negedge clk 10 | always_ff @(negedge clk, negedge RST_n) 11 | if(!RST_n) begin 12 | ff1 <= 1'b0; 13 | rst_n <= 1'b0; 14 | end 15 | else begin 16 | ff1 <= 1'b1; 17 | rst_n <= ff1; 18 | end 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /Project/FP_modules/FP_adder_doc.txt: -------------------------------------------------------------------------------- 1 | The addition of two floating-point numbers is complex, since their exponents could differ by a great amount and their mantissas are unsigned representations. The following steps describe how the FP Adder works in detail. 2 | 3 | 1. Compare two exponents, determine the smaller one, and calculate the absolute difference between them. The larger E will be the common E (for now). 4 | 5 | 2. Append |E (reduction OR of exponent) in front of both mantissas. Now both numbers of interest are of 24-bit. 6 | 7 | 3. Shift the mantissa (including the appended digit) with a smaller exponent to the right, where the shift amount is the lower 5 bits of the difference between exponents. The maximum shift amount should be 22-bit, or the shifted number is too small to be considered. 8 | 9 | 4. Convert both appended then shifted mantissa into 2’s complement format by looking at the sign bit. Now both numbers are in 25-bit 2’s complement. 10 | 11 | 5. Add two 25-bit numbers and get a 25-bit result. If the result overflows either positively or negatively, an increment in the common exponent is needed. Note that this overflow is NOT an external value overflow (the FP number cannot be represented) but an internal overflow (the result can be correctly represented). 12 | 13 | 6. Convert the 25-bit 2’s complement back to a 25-bit signed number with the MSB being the final sign and the rest 24-bit being the unsigned value. This step should have no loss of precision. Now, the MSB is the sign, and the rest 24-bit is to be further processed. 14 | 15 | 7. If an overflow occurs, shift the lower 24-bit to the right, appending 1 in MSB and discarding the LSB; if the lower 24-bit has leading zeros, a left shift is needed, where the shift amount is determined by the number of leading zero(s), and the common exponent is decremented by the shift amount. This 24-bit result should have a MSB of 1 now. 16 | 17 | 8. The resulting mantissa will be the lower 23-bit of the final 24-bit result. The exponent is the final common exponent. The sign is the MSB of is the final sign. 18 | -------------------------------------------------------------------------------- /Project/FP_modules/float_to_signed_int.sv: -------------------------------------------------------------------------------- 1 | module float_to_signed_int(FP_val, signed_int_val); 2 | 3 | input [31:0] FP_val; // input is 32 bit float 4 | output signed [31:0] signed_int_val; // output is 32 bit signed int 5 | 6 | logic [22:0] M; // mantissa 7 | logic [7:0] E; // exponent 8 | 9 | logic [30:0] abs_int; // unsigned value of (1.M) * 2^(E-127) 10 | 11 | assign M = FP_val[22:0]; 12 | assign E = FP_val[30:23]; 13 | 14 | // calculate the absolute value of the integer, choosing correct shift direction according to E 15 | assign abs_int = E >= 8'd150 ? {8'h00, 1'b1, M} << (E - 8'd150) : {8'h00, 1'b1, M} >> (8'd150 - E); 16 | 17 | // convert abs_int to signed_int_val with saturation/zeroing logic 18 | assign signed_int_val = E >= 8'd182 ? ((FP_val[31]) ? 32'h80000000 : 32'h7FFFFFFF) : // if E too large, saturate 19 | E < 8'd127 ? 32'h00000000 : // if E too small, zero 20 | (FP_val[31]) ? {1'b1, (~abs_int + 31'd00000001)} : {1'b0, abs_int}; // if neither of the extremes, output according to sign 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Project/FP_modules/float_to_signed_int_tb.sv: -------------------------------------------------------------------------------- 1 | module float_to_signed_int_tb(); 2 | 3 | import FP_special_values::*; 4 | 5 | logic [31:0] FP_val; // input is 32 bit float 6 | logic signed [31:0] signed_int_val; // output is 32 bit signed int 7 | 8 | int exp_val; 9 | int precision_right_shift; 10 | 11 | float_to_signed_int iDUT( 12 | .FP_val(FP_val), 13 | .signed_int_val(signed_int_val) 14 | ); 15 | 16 | task automatic test_float_to_signed_int(shortreal test_val); 17 | FP_val = $shortrealtobits(test_val); 18 | exp_val = $rtoi(test_val); 19 | precision_right_shift = FP_val[30:23] <= 8'd150 ? 0 : 20 | FP_val[30:23] < 8'd181 ? int'(FP_val[30:23] - 8'd150) : 21 | 0; 22 | #1; 23 | // if FP_val's abs value is too large, PASS if saturated 24 | if((FP_val[30:23] >= 8'd182) && (signed_int_val[31] ? signed_int_val === 32'h80000000 : signed_int_val === 32'h7FFFFFFF) ) begin 25 | return; 26 | end 27 | 28 | // if FP_val's abs value is between zero and one, PASS if zeroed 29 | if((FP_val[30:23] < 8'd127) && ~|signed_int_val) begin 30 | return; 31 | end 32 | 33 | // allow -1 ~ +1 difference on the scale of valid precision due to shortrealtobits and rtoi error 34 | // if E in FP input is too large or too small, this if check will automatically let it PASS, since the converted int is meaningless anyways 35 | if((signed_int_val >>> precision_right_shift) > (exp_val >>> precision_right_shift) + 1 || 36 | (signed_int_val >>> precision_right_shift) < (exp_val >>> precision_right_shift) - 1) begin 37 | $display("WRONG ANSWER! after precision_right_shift %d bits, expecting %b got %b", precision_right_shift, signed_int_val >>> precision_right_shift, exp_val >>> precision_right_shift); 38 | $stop(); 39 | end 40 | endtask 41 | 42 | initial begin 43 | // random tests 44 | for(int i = 0; i < 1000; i++) begin 45 | test_float_to_signed_int($random()); // intentionally not casting to use the 32 random bits as shortreal 46 | end 47 | 48 | // random tests of small integers 49 | for(int i = 0; i < 1000; i++) begin 50 | test_float_to_signed_int($itor($random() % 100000)); 51 | end 52 | 53 | // special FP value tests 54 | for(int i = 0; i < 16; i++) begin 55 | test_float_to_signed_int($bitstoshortreal(SPECIAL_VALS_ARR[i])); 56 | end 57 | 58 | $display("ALL TESTS PASSED!!!"); 59 | $stop(); 60 | end 61 | 62 | endmodule 63 | -------------------------------------------------------------------------------- /Project/FP_modules/left_shifter.sv: -------------------------------------------------------------------------------- 1 | // Another self-explaining module 2 | module left_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {In[22:0],1'b0} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {shft_stg1[21:0],2'b0} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {shft_stg2[19:0],4'b0} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {shft_stg3[15:0],8'b0} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {shft_stg4[7:0],16'b0} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/FP_modules/right_shifter.sv: -------------------------------------------------------------------------------- 1 | // A self-explaining module 2 | module right_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {1'b0,In[23:1]} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {2'b0,shft_stg1[23:2]} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {4'b0,shft_stg2[23:4]} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {8'b0,shft_stg3[23:8]} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {16'b0,shft_stg4[23:16]} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/FP_modules/signed_int_to_float_tb.sv: -------------------------------------------------------------------------------- 1 | module signed_int_to_float_tb(); 2 | 3 | logic signed [31:0] signed_int_val; 4 | logic [31:0] FP_val; 5 | 6 | shortreal temp; 7 | logic [31:0] exp_val; 8 | 9 | signed_int_to_float iDUT( 10 | .signed_int_val(signed_int_val), 11 | .FP_val(FP_val) 12 | ); 13 | 14 | task automatic test_signed_int_to_float(int test_val); 15 | signed_int_val = test_val; 16 | temp = $itor(test_val); 17 | exp_val = $shortrealtobits(temp); 18 | #1; 19 | // if signs do not match, doom to fail! 20 | if(FP_val[31] !== exp_val[31]) begin 21 | $display("WRONG ANSWER! %d should be converted to %b, not %b", signed_int_val, exp_val, FP_val); 22 | $stop(); 23 | end 24 | 25 | // for normalized FP numbers (all 32-bits signed ints are), consider {S, E + 1, 23'h00000000} the same as {S, E, 23'h7FFFFFFF} due to rounding errors of itor and shortrealtobits 26 | if(&FP_val[22:0] && (FP_val[30:23] == exp_val[30:23] - 8'h01) || 27 | &exp_val[22:0] && (exp_val[30:23] == FP_val[30:23] - 8'h01)) begin 28 | return; 29 | end 30 | 31 | // allow -1 ~ +1 difference (on the LSBs of M) due to shortrealtobits and bitstoshortreal error 32 | if((FP_val[30:23] === exp_val[30:23]) && 33 | (signed'({2'b00, FP_val[22:0]}) >= signed'({2'b00, exp_val[22:0]}) - signed'(25'h000001)) && 34 | (signed'({2'b00, FP_val[22:0]}) <= signed'({2'b00, exp_val[22:0]}) + signed'(25'h000001))) begin 35 | return; 36 | end 37 | 38 | // if not fall into any of the 2 categories above, testcase FAILED 39 | $display("WRONG ANSWER! %d should be converted to %b, not %b", signed_int_val, exp_val, FP_val); 40 | $stop(); 41 | endtask 42 | 43 | initial begin 44 | 45 | // test zero 46 | test_signed_int_to_float(32'h00000000); 47 | 48 | // test largest positive signed int 49 | test_signed_int_to_float(32'h7FFFFFFF); 50 | 51 | // test most negative signed int 52 | test_signed_int_to_float(32'h80000000); 53 | 54 | // random tests 55 | for(int i = 0; i < 1000; i++) begin 56 | test_signed_int_to_float($random()); 57 | end 58 | 59 | $display("ALL TESTS PASSED!!!"); 60 | $stop(); 61 | end 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/CPU_factory/module_test.cr.mti: -------------------------------------------------------------------------------- 1 | I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/ram_2p.v {1 {vlog -work work -vopt -stats=none I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/ram_2p.v 2 | Model Technology ModelSim SE vlog 10.3c Compiler 2014.07 Jul 19 2014 3 | -- Compiling module ram_2p 4 | 5 | Top level modules: 6 | ram_2p 7 | 8 | } {} {}} I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/stack.sv {1 {vlog -work work -vopt -sv -stats=none I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/stack.sv 9 | Model Technology ModelSim SE vlog 10.3c Compiler 2014.07 Jul 19 2014 10 | -- Compiling module stack 11 | 12 | Top level modules: 13 | stack 14 | 15 | } {} {}} I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/stack_tb.sv {1 {vlog -work work -vopt -sv -stats=none I:/ECE554/ECE554_SP23/Project/InOrderSuperscalarCPU/CPU_factory/stack_tb.sv 16 | Model Technology ModelSim SE vlog 10.3c Compiler 2014.07 Jul 19 2014 17 | -- Compiling module stack_tb 18 | 19 | Top level modules: 20 | stack_tb 21 | 22 | } {} {}} 23 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/CPU_factory/ram_2p.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram_2p.v"] 5 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/CPU_factory/vsim.wlf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/InOrderSuperscalarCPU/CPU_factory/vsim.wlf -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/CPU_factory/work/@_opt/_data/exemptwh7ksi: -------------------------------------------------------------------------------- 1 | =B>f3Cn@lSj^fNXHnlbT4bz7a1j?[DNPF6LP;8?f2HE03,16Pi4aWZH;S2kZnN@CaMoL[37,16Y`VN^L MUL 4 | // 001 ==> UMUL 5 | // 010 ==> ADDF 6 | // 011 ==> SUBF 7 | // 100 ==> MULF 8 | // 101 ==> ITF 9 | // 110 ==> FTI 10 | // 111 ==> undefined 11 | 12 | `include "common_params.inc" 13 | 14 | input clk; 15 | input [31:0] src1, src0; 16 | input [2:0] func; // selects function to perform 17 | output reg [31:0] dst_EX_DM; 18 | output ov, zr, neg; 19 | 20 | logic [31:0] ifadd_OUT, ifmul_OUT, iftoi_OUT, iitof_OUT, iimul_OUT; 21 | 22 | logic [31:0] OUT; 23 | 24 | /////////////////////// 25 | // compute modules // 26 | ///////////////////// 27 | 28 | FP_adder ifadd( 29 | .A(src1), 30 | .B(func==SUBF ? {~src0[31], src0[30:0]} : src0), // flip second operand if doing A - B 31 | .out(ifadd_OUT) 32 | ); 33 | 34 | FP_mul ifmul( 35 | .A(src1), 36 | .B(src0), 37 | .OUT(ifmul_OUT) 38 | ); 39 | 40 | float_to_signed_int iftoi( 41 | .FP_val(src1), 42 | .signed_int_val(iftoi_OUT) 43 | ); 44 | 45 | signed_int_to_float iitof( 46 | .signed_int_val(src1), 47 | .FP_val(iitof_OUT) 48 | ); 49 | 50 | int_mul_16by16 iimul( 51 | .A(src1), 52 | .B(src0), 53 | .sign(~func[0]), // 0 ==> MUL 1 ==> UMUL 54 | .OUT(iimul_OUT) 55 | ); 56 | 57 | /////////////////////////////////// 58 | // Multiplexing function of ALU // 59 | ///////////////////////////////// 60 | assign OUT = (func==MUL || func==UMUL) ? iimul_OUT : 61 | (func==ADDF || func==SUBF) ? ifadd_OUT : 62 | (func==MULF) ? ifmul_OUT : 63 | (func==ITF) ? iitof_OUT : 64 | (func==FTI) ? iftoi_OUT : 65 | 32'hDEADDEAD; // undefined behavior 66 | 67 | ///////////////////////// 68 | // Set flag variables // 69 | /////////////////////// 70 | // these 7 instructions can NEVER overflow (FP operations are saturating following their own rules) 71 | assign ov = 1'b0; 72 | 73 | // assign zero flag according to if output is in normal format or FP format 74 | assign zr = (func==MUL || func==UMUL || func==FTI) ? ~|OUT : ~|OUT[30:0]; 75 | 76 | // assign neg flag according to if output is signed or unsigned 77 | assign neg = (func==UMUL) ? 1'b0 : OUT[31]; 78 | 79 | ////////////////////////// 80 | // Flop the ALU result // 81 | //////////////////////// 82 | always @(posedge clk) 83 | dst_EX_DM <= OUT; 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/fifo.sv: -------------------------------------------------------------------------------- 1 | // A fifo queue that allows read and write at same time 2 | module fifo( 3 | input clk, // 50MHz clk 4 | input rst_n, // asynch active low reset 5 | input w_en, // write enable 6 | input r_en, // read enable 7 | input [7:0] in_data, // data to be stored in queue 8 | output q_full, // indicates queue is full 9 | output q_empty, // indicates queue is empty 10 | output [7:0] out_data, // data to be read in queue 11 | output [3:0] contain_num // Number of used entires in the queue 12 | ); 13 | 14 | ///////////////////////////// 15 | // Declare reg and wires // 16 | /////////////////////////// 17 | reg [3:0] head_ptr, tail_ptr; // Insert into head, pop from tail 18 | reg [7:0] buffer [0:7]; // 8 entry buffer with 8bits wide data 19 | 20 | // When all 8 entries are filled, the lower 3 bits of the pointer will be same, but the highest bit will be different 21 | assign q_full = tail_ptr[2:0] == head_ptr[2:0] && tail_ptr[3] == ~head_ptr[3]; 22 | // When head ptr and tail ptr are same, the queue is empty 23 | assign q_empty = tail_ptr == head_ptr; 24 | // Number of used/filled entry in the queue 25 | assign contain_num = head_ptr - tail_ptr; 26 | 27 | ///////////////////////////////// 28 | // Read data from the buffer // 29 | /////////////////////////////// 30 | assign out_data = buffer[tail_ptr[2:0]]; //Constantly output the data from the tail_ptr 31 | 32 | /////////////////////////////////// 33 | // Write data into the buffer // 34 | ///////////////////////////////// 35 | always_ff @(posedge clk) 36 | if (w_en && !q_full) 37 | buffer[head_ptr[2:0]] <= in_data; 38 | 39 | /////////////////////////////// 40 | // Tail ptr control logic // 41 | ///////////////////////////// 42 | always_ff @(posedge clk, negedge rst_n) 43 | if (!rst_n) 44 | tail_ptr <= 4'h0; 45 | else if (r_en && !q_empty) // Increment tail_ptr when read enabled and queue is not empty 46 | tail_ptr <= tail_ptr + 4'h1; // Increment tail_ptr == pop an entry from the queue 47 | 48 | /////////////////////////////// 49 | // Head ptr control logic // 50 | ///////////////////////////// 51 | always_ff @(posedge clk, negedge rst_n) 52 | if (!rst_n) 53 | head_ptr <= 4'h0; 54 | else if (w_en && !q_full) // Increment head ptr when write enabled and queue is not full 55 | head_ptr <= head_ptr + 4'h1; 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/float_to_signed_int.sv: -------------------------------------------------------------------------------- 1 | module float_to_signed_int(FP_val, signed_int_val); 2 | 3 | input [31:0] FP_val; // input is 32 bit float 4 | output signed [31:0] signed_int_val; // output is 32 bit signed int 5 | 6 | logic [22:0] M; // mantissa 7 | logic [7:0] E; // exponent 8 | 9 | logic [30:0] abs_int; // unsigned value of (1.M) * 2^(E-127) 10 | 11 | assign M = FP_val[22:0]; 12 | assign E = FP_val[30:23]; 13 | 14 | // calculate the absolute value of the integer, choosing correct shift direction according to E 15 | assign abs_int = E >= 8'd150 ? {8'h00, 1'b1, M} << (E - 8'd150) : {8'h00, 1'b1, M} >> (8'd150 - E); 16 | 17 | // convert abs_int to signed_int_val with saturation/zeroing logic 18 | assign signed_int_val = E >= 8'd182 ? ((FP_val[31]) ? 32'h80000000 : 32'h7FFFFFFF) : // if E too large, saturate 19 | E < 8'd127 ? 32'h00000000 : // if E too small, zero 20 | (FP_val[31]) ? {1'b1, (~abs_int + 31'd00000001)} : {1'b0, abs_int}; // if neither of the extremes, output according to sign 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/instr_mem.v: -------------------------------------------------------------------------------- 1 | module IM(clk,addr0,addr1,instr0,instr1); 2 | /////////////////////////////////////////////////////////////////////////////\\ 3 | // This module implements the instruction memory logic. It takes one address \\ 4 | // inputs and fetch the two sequential instructions from the instruction memory\\ 5 | // The instruction memory is already read_enabled because there is no reason // 6 | // to not read an instruction // 7 | /////////////////////////////////////////////////////////////////////////////// 8 | 9 | input clk; 10 | input [13:0] addr0,addr1; 11 | 12 | 13 | output reg [31:0] instr0, instr1; // output of insturction memory 14 | 15 | reg [31:0]instr_mem[0:255]; // 16K*32 instruction memory 16 | 17 | /////////////////////////////////// 18 | // Memory is flopped on negedge // 19 | ///////////////////////////////// 20 | always @(negedge clk) 21 | instr0 <= instr_mem[addr0]; 22 | instr1 <= instr_mem[addr1]; 23 | 24 | initial begin 25 | $readmemh("../instr.hex",instr_mem); 26 | end 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/int_mul_16by16.sv: -------------------------------------------------------------------------------- 1 | module int_mul_16by16(A, B, sign, OUT); 2 | 3 | input [15:0] A; // 16 bit integer input 4 | input [15:0] B; // 16 bit integer input 5 | input sign; // signed multiply when set, unsigned multiply when unsigned 6 | output [31:0] OUT; // the product of A*B 7 | 8 | logic signed [16:0] A_eff, B_eff; 9 | logic signed [33:0] product; 10 | 11 | assign A_eff = {sign ? A[15] : 1'b0, A}; 12 | assign B_eff = {sign ? B[15] : 1'b0, B}; 13 | 14 | assign product = A_eff * B_eff; 15 | 16 | assign OUT = product[31:0]; 17 | 18 | endmodule -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/left_shifter.sv: -------------------------------------------------------------------------------- 1 | // Another self-explaining module 2 | module left_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {In[22:0],1'b0} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {shft_stg1[21:0],2'b0} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {shft_stg2[19:0],4'b0} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {shft_stg3[15:0],8'b0} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {shft_stg4[7:0],16'b0} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/ram_2p.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram_2p.v"] 5 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/review_model_list.txt: -------------------------------------------------------------------------------- 1 | pc - how does pc increment? What is the dependency? 2 | IM - Done modifying module, still need top level layout 3 | id - decode two instructions at same time and determine dependency to decide pc increment and delay 4 | 5 | rf - need to allow two write and four read, hardcode the writeEN logic for each register file if necessary 6 | - when two writes write into same addr, use the later one 7 | - when read value from previous cycle, bypass 8 | - if two fetched instructions have dependency, then only the first read matters because the second one will be stalled anyway 9 | - finished implementing bypass logic. still need to make sure the write part works 10 | src_mux - dependency issue 11 | 12 | EXECUTE: 13 | alu - need double instantiate, each alu reserved for each instruction 14 | extended_ALU - need double instantiate, each alu reserved for each instruction 15 | stack - has single instantiate, allow multiple push in same cycle? Need to verify synthesis and logic 16 | 17 | DM - double read, double write 18 | IM - Done LWI, has single IM, allow multiple read 19 | dst_mux - write two values back 20 | br_bool - look at both instruction, if branch and no dependency between the two instructions, jump -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/rf.v: -------------------------------------------------------------------------------- 1 | module rf(clk,p0_addr,p1_addr,p0,p1,re0,re1,dst_addr,dst,we,hlt); 2 | ////////////////////////////////////////////////////////////////// 3 | // Triple ported register file. Two read ports (p0 & p1), and // 4 | // one write port (dst). Data is written on clock high, and // 5 | // read on clock low ////////////////////////////////////////// 6 | ////////////////////// 7 | 8 | input clk; 9 | input [4:0] p0_addr, p1_addr; // two read port addresses 10 | input re0,re1; // read enables (power not functionality) 11 | input [4:0] dst_addr; // write address 12 | input [31:0] dst; // dst bus 13 | input we; // write enable 14 | input hlt; // not a functional input. Used to dump register contents when 15 | // test is halted. (No longer used) 16 | 17 | output [31:0] p0,p1; // output read ports 18 | 19 | wire r0_bypass, r1_bypass; // RF bypass 20 | wire [31:0] p0_raw, p1_raw; // raw read output from SRAM 21 | 22 | ///////////////////////////////////////////////////////////////////// 23 | // Instantiate two dualport memory to create a tripple port rf // 24 | // Always write same data to both sram instance at the same time // 25 | ////////////////////////////////////////////////////////////////// 26 | dualPort32x32 sram0( 27 | .clk(clk), 28 | .we(we), 29 | .re(re0), 30 | .waddr(dst_addr), 31 | .raddr(p0_addr), 32 | .wdata(dst), 33 | .rdata(p0_raw) 34 | ); 35 | dualPort32x32 sram1( 36 | .clk(clk), 37 | .we(we), 38 | .re(re1), 39 | .waddr(dst_addr), 40 | .raddr(p1_addr), 41 | .wdata(dst), 42 | .rdata(p1_raw) 43 | ); 44 | 45 | // Bypass if any read register is the same as the write register and both re and we are high 46 | assign r0_bypass = ~|(p0_addr ^ dst_addr) & re0 & we; 47 | assign r1_bypass = ~|(p1_addr ^ dst_addr) & re1 & we; 48 | 49 | // R0 always stay at 32'h0000_0000 50 | assign p0 = ~|p0_addr ? 32'h0000_0000 : (r0_bypass ? dst : p0_raw); 51 | assign p1 = ~|p1_addr ? 32'h0000_0000 : (r1_bypass ? dst : p1_raw); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/right_shifter.sv: -------------------------------------------------------------------------------- 1 | // A self-explaining module 2 | module right_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {1'b0,In[23:1]} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {2'b0,shft_stg1[23:2]} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {4'b0,shft_stg2[23:4]} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {8'b0,shft_stg3[23:8]} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {16'b0,shft_stg4[23:16]} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/InOrderSuperscalarCPU/rst_synch.v: -------------------------------------------------------------------------------- 1 | module rst_synch(clk,RST_n,pll_locked,rst_n); 2 | 3 | input clk; // 50MHz clock 4 | input RST_n; // non synched reset from push button 5 | input pll_locked; // don't deassert reset till PLL is locked 6 | output reg rst_n; // synched on deassert to negedge of clock 7 | 8 | reg q1; 9 | 10 | //////////////////////////////////////////////// 11 | // rst_n is asserted asynch, but deasserted // 12 | // syncronized to negedge clock. Two flops // 13 | // are used for metastability purposes. // 14 | //////////////////////////////////////////// 15 | always @(negedge clk, negedge RST_n) 16 | if (!RST_n) 17 | begin 18 | q1 <= 1'b0; 19 | rst_n <= 1'b0; 20 | end 21 | else 22 | begin 23 | q1 <= pll_locked; 24 | rst_n <= q1; 25 | end 26 | 27 | endmodule -------------------------------------------------------------------------------- /Project/ML/1_epoch_suck_model/sucklin2.txt: -------------------------------------------------------------------------------- 1 | 1341.8863525390625 2 | -74.2618408203125 3 | -231.5377655029297 4 | 491.8951416015625 5 | 1264.76171875 6 | 874.4058837890625 7 | 678.2730712890625 8 | 375.5534362792969 9 | 543.5518798828125 10 | 844.8167724609375 11 | -1088.6572265625 12 | 484.0810241699219 13 | -243.37448120117188 14 | -641.204345703125 15 | -135.8201904296875 16 | -755.3677978515625 17 | -775.7200927734375 18 | -942.0314331054688 19 | 740.607177734375 20 | -1094.187744140625 21 | -266.097900390625 22 | 756.70947265625 23 | 1045.6005859375 24 | 132.98687744140625 25 | -1639.2977294921875 26 | 1135.6435546875 27 | -263.630615234375 28 | -341.5257568359375 29 | -1678.06396484375 30 | -95.849853515625 31 | -681.9364013671875 32 | 1412.2952880859375 33 | -78.08181762695312 34 | -340.6398620605469 35 | 582.38134765625 36 | 863.5568237304688 37 | 938.45556640625 38 | 1400.4974365234375 39 | 41.75019836425781 40 | 1323.33935546875 41 | -51.098541259765625 42 | 1626.0419921875 43 | 392.42950439453125 44 | -204.6814422607422 45 | -878.81591796875 46 | 2111.305908203125 47 | 706.6630249023438 48 | 101.86529541015625 49 | -803.2490234375 50 | 594.078369140625 51 | 552.1142578125 52 | -338.94232177734375 53 | -283.721923828125 54 | -951.3861083984375 55 | 1388.51904296875 56 | -295.06512451171875 57 | 776.38232421875 58 | 1189.591064453125 59 | 1685.56787109375 60 | 965.7435913085938 61 | 1885.072265625 62 | 873.0322265625 63 | 972.7838134765625 64 | -221.3393096923828 65 | 610.6025390625 66 | -92.14788055419922 67 | -554.4786987304688 68 | -220.164794921875 69 | 714.1553344726562 70 | -1512.7659912109375 71 | 2229.091796875 72 | 1430.991455078125 73 | -606.7740478515625 74 | -799.7613525390625 75 | 1208.58447265625 76 | 170.59873962402344 77 | 995.3370361328125 78 | 378.02081298828125 79 | 1384.8642578125 80 | 1052.2244873046875 81 | 587.210693359375 82 | 1074.9827880859375 83 | 902.2384033203125 84 | -1359.478759765625 85 | -------------------------------------------------------------------------------- /Project/ML/1_epoch_suck_model/sucklin3.txt: -------------------------------------------------------------------------------- 1 | 808.5001220703125 2 | -1187.11767578125 3 | 1257.9384765625 4 | 229.59437561035156 5 | -215.4676513671875 6 | 189.87770080566406 7 | -114.54266357421875 8 | -398.49310302734375 9 | 444.9416809082031 10 | 377.60028076171875 11 | -------------------------------------------------------------------------------- /Project/ML/1_epoch_test_model/test_lin2.txt: -------------------------------------------------------------------------------- 1 | -828.8057861328125 2 | -63.87782287597656 3 | -166.8302001953125 4 | 1017.1023559570312 5 | 250.56385803222656 6 | -195.8695526123047 7 | -330.8076477050781 8 | 543.3116455078125 9 | 1037.580078125 10 | 67.43585205078125 11 | -201.38400268554688 12 | 696.0768432617188 13 | 1075.2109375 14 | -1159.2982177734375 15 | 192.5650634765625 16 | 821.8472900390625 17 | -90.83811950683594 18 | -598.3218994140625 19 | 1405.809326171875 20 | 931.8538818359375 21 | -42.07508850097656 22 | -210.67845153808594 23 | 1065.4088134765625 24 | 465.3375244140625 25 | -376.35198974609375 26 | -108.99732208251953 27 | 516.1135864257812 28 | -43.052154541015625 29 | 1390.607666015625 30 | 19.871410369873047 31 | 587.9170532226562 32 | 766.2313232421875 33 | 707.809326171875 34 | -1097.939697265625 35 | 480.05975341796875 36 | -338.9356689453125 37 | -400.44122314453125 38 | 73.7978515625 39 | 332.76336669921875 40 | 410.802978515625 41 | -260.40301513671875 42 | -392.1084899902344 43 | -446.3805236816406 44 | 487.18084716796875 45 | 185.88165283203125 46 | 723.5257568359375 47 | -60.651397705078125 48 | 1141.5428466796875 49 | 1110.67529296875 50 | 965.38623046875 51 | 1097.49365234375 52 | 702.4888305664062 53 | 615.5809326171875 54 | -639.920654296875 55 | 344.3090515136719 56 | 1114.323974609375 57 | 542.4009399414062 58 | 1067.46875 59 | -517.992431640625 60 | 643.9312133789062 61 | 155.4817352294922 62 | 1360.985107421875 63 | 367.5865173339844 64 | -472.7430114746094 65 | 765.5786743164062 66 | 412.3453063964844 67 | 130.4664306640625 68 | 2.6061553955078125 69 | 1340.16064453125 70 | 426.0854187011719 71 | 398.5498352050781 72 | 1362.024658203125 73 | 31.43708038330078 74 | -148.87887573242188 75 | -376.9019775390625 76 | -680.8472900390625 77 | 135.11941528320312 78 | 615.6561279296875 79 | 484.5976867675781 80 | 512.2449340820312 81 | 54.38958740234375 82 | 17.474945068359375 83 | -101.80853271484375 84 | 1243.4039306640625 85 | -------------------------------------------------------------------------------- /Project/ML/1_epoch_test_model/test_lin3.txt: -------------------------------------------------------------------------------- 1 | -606.526123046875 2 | 283.82000732421875 3 | -685.3316040039062 4 | 48.2784423828125 5 | 495.1758117675781 6 | 2.196441650390625 7 | -1083.3636474609375 8 | -24.19009017944336 9 | 469.40936279296875 10 | 703.61376953125 11 | 170.84327697753906 12 | -217.8706512451172 13 | -804.8472900390625 14 | -414.0002746582031 15 | 11.307403564453125 16 | 335.2110290527344 17 | 11.803520202636719 18 | -92.77179718017578 19 | 395.2332458496094 20 | -384.901611328125 21 | 93.07528686523438 22 | 38.43629455566406 23 | -32.78251647949219 24 | -346.5498352050781 25 | -177.09266662597656 26 | 470.38104248046875 27 | 197.1726837158203 28 | 219.44113159179688 29 | 21.01883316040039 30 | 657.8281860351562 31 | -1043.072998046875 32 | 75.83096313476562 33 | -1036.962646484375 34 | 529.2368774414062 35 | 675.68603515625 36 | 75.57441711425781 37 | -------------------------------------------------------------------------------- /Project/ML/20_epoch_good_model/goodlin2.txt: -------------------------------------------------------------------------------- 1 | -859.68115234375 2 | 535.707763671875 3 | -325.00732421875 4 | 168.26724243164062 5 | 310.720703125 6 | -612.7028198242188 7 | -8.43316650390625 8 | 1417.1016845703125 9 | 897.155029296875 10 | -22.393692016601562 11 | -651.2364501953125 12 | 1108.6749267578125 13 | 588.028564453125 14 | 446.95025634765625 15 | 573.5637817382812 16 | -185.76559448242188 17 | 236.45709228515625 18 | -357.1065673828125 19 | -486.380126953125 20 | 1035.718017578125 21 | -42.7138671875 22 | 462.00201416015625 23 | 352.1968078613281 24 | -1009.351318359375 25 | 1482.0013427734375 26 | 1074.1553955078125 27 | 1835.008056640625 28 | -146.1219482421875 29 | -1105.57763671875 30 | -1528.376220703125 31 | 1032.652099609375 32 | 47.65088653564453 33 | 1467.8629150390625 34 | 475.19818115234375 35 | 370.30975341796875 36 | -746.2322387695312 37 | 948.2738647460938 38 | -441.35162353515625 39 | 809.9871826171875 40 | -1424.9775390625 41 | 1219.57080078125 42 | 553.188720703125 43 | -119.7432861328125 44 | 369.2823486328125 45 | 350.5956115722656 46 | 364.1258544921875 47 | 332.49005126953125 48 | 510.24322509765625 49 | -379.55096435546875 50 | 438.9723815917969 51 | 1417.65185546875 52 | 1305.3258056640625 53 | -835.7415161132812 54 | -645.857421875 55 | 575.9520874023438 56 | 221.71014404296875 57 | -463.54742431640625 58 | 142.54273986816406 59 | 781.5054931640625 60 | -262.0531921386719 61 | -414.1039123535156 62 | -1316.843017578125 63 | -94.89027404785156 64 | -29.409027099609375 65 | 670.3176879882812 66 | 865.370361328125 67 | 1323.2056884765625 68 | 797.701171875 69 | -201.8253936767578 70 | 419.954833984375 71 | 584.7078857421875 72 | -682.354248046875 73 | 1340.015380859375 74 | -267.23516845703125 75 | 1981.365478515625 76 | -38.81175231933594 77 | 673.5057983398438 78 | -356.3337097167969 79 | -984.1531982421875 80 | 894.9075927734375 81 | -213.63563537597656 82 | 125.59307098388672 83 | -510.0553894042969 84 | 871.8192138671875 85 | -------------------------------------------------------------------------------- /Project/ML/20_epoch_good_model/goodlin3.txt: -------------------------------------------------------------------------------- 1 | -165.947265625 2 | -575.27734375 3 | 1568.849853515625 4 | 227.26449584960938 5 | -644.7427368164062 6 | -1306.81982421875 7 | -648.119873046875 8 | -413.79669189453125 9 | 768.4650268554688 10 | 117.34295654296875 11 | -------------------------------------------------------------------------------- /Project/ML/20_epoch_supercharged/goodlin2.txt: -------------------------------------------------------------------------------- 1 | -492.9776611328125 2 | -1521.655029296875 3 | 842.1629028320312 4 | 2060.29833984375 5 | 131.01541137695312 6 | -2110.4248046875 7 | 904.64453125 8 | -2142.37109375 9 | -2797.8564453125 10 | -477.3824462890625 11 | -1666.96240234375 12 | -168.01519775390625 13 | 2300.402587890625 14 | 1456.6605224609375 15 | -1806.0047607421875 16 | -1453.7412109375 17 | 216.10638427734375 18 | -636.4349975585938 19 | 1378.33935546875 20 | -3356.596435546875 21 | -1800.30322265625 22 | 200.43975830078125 23 | -1135.1826171875 24 | -2309.50830078125 25 | 2160.641845703125 26 | -655.7174072265625 27 | 823.0007934570312 28 | -1846.06982421875 29 | -1086.6103515625 30 | -3381.885009765625 31 | 2110.160888671875 32 | 1496.526611328125 33 | -272.6108703613281 34 | 127.14892578125 35 | -2134.59619140625 36 | -173.75634765625 37 | 1557.799072265625 38 | 1441.7733154296875 39 | 590.6507568359375 40 | -1273.3619384765625 41 | 820.6874389648438 42 | 2202.53955078125 43 | -1873.275634765625 44 | -746.5927734375 45 | -538.067138671875 46 | -3001.3935546875 47 | -2700.147705078125 48 | -862.935546875 49 | -687.5022583007812 50 | 2091.95654296875 51 | -845.7938842773438 52 | -1085.1153564453125 53 | 1816.054443359375 54 | -744.8148193359375 55 | -1775.170166015625 56 | 1026.0855712890625 57 | 2099.60400390625 58 | -636.1129760742188 59 | 1397.4759521484375 60 | -13.7147216796875 61 | 800.580322265625 62 | -1233.759765625 63 | -1045.7100830078125 64 | -14.141845703125 65 | 3007.777099609375 66 | -1273.734375 67 | -1335.29296875 68 | 1607.645263671875 69 | -1005.4912719726562 70 | 952.3609619140625 71 | -659.721435546875 72 | -642.2232666015625 73 | -1716.99658203125 74 | -2087.173828125 75 | 607.549072265625 76 | -2013.179931640625 77 | -1762.119873046875 78 | 182.72247314453125 79 | -2410.309326171875 80 | -152.45111083984375 81 | -358.28985595703125 82 | -2594.605224609375 83 | -1070.525390625 84 | 1874.8221435546875 85 | -------------------------------------------------------------------------------- /Project/ML/20_epoch_supercharged/goodlin3.txt: -------------------------------------------------------------------------------- 1 | 4364.6689453125 2 | -592.01025390625 3 | 489.88262939453125 4 | -1032.1650390625 5 | 163.8580322265625 6 | 1061.6033935546875 7 | 164.12322998046875 8 | 6.2245941162109375 9 | -575.1688842773438 10 | 1890.7314453125 11 | 948.7509765625 12 | -927.6839599609375 13 | 2011.046875 14 | 2400.54052734375 15 | -745.994384765625 16 | 53.1031494140625 17 | 1298.990478515625 18 | -1981.318603515625 19 | -889.1981201171875 20 | 262.359130859375 21 | -3723.3583984375 22 | -1081.5439453125 23 | -3184.938232421875 24 | 508.8255615234375 25 | 4049.587158203125 26 | 1036.8375244140625 27 | 2952.37158203125 28 | -1321.16943359375 29 | 1682.82568359375 30 | -163.6282958984375 31 | -2.03875732421875 32 | -423.74859619140625 33 | -1334.3272705078125 34 | -3972.678466796875 35 | -1043.452880859375 36 | -2706.283203125 37 | -------------------------------------------------------------------------------- /Project/SourceCode/Line_Buffer1.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "Shift register (RAM-based)" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Line_Buffer1.v"] 5 | set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "Line_Buffer1.bsf"] 6 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL.cmp: -------------------------------------------------------------------------------- 1 | component PLL is 2 | port ( 3 | refclk : in std_logic := 'X'; -- clk 4 | rst : in std_logic := 'X'; -- reset 5 | outclk_0 : out std_logic; -- clk 6 | outclk_1 : out std_logic; -- clk 7 | outclk_2 : out std_logic; -- clk 8 | outclk_3 : out std_logic; -- clk 9 | outclk_4 : out std_logic; -- clk 10 | locked : out std_logic -- export 11 | ); 12 | end component PLL; 13 | 14 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL.ppf: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL.sip: -------------------------------------------------------------------------------- 1 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_NAME "altera_pll" 2 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -entity "PLL" -library "lib_PLL" -name IP_TOOL_ENV "mwpim" 4 | set_global_assignment -library "lib_PLL" -name SPD_FILE [file join $::quartus(sip_path) "PLL.spd"] 5 | 6 | set_global_assignment -library "lib_PLL" -name MISC_FILE [file join $::quartus(sip_path) "PLL_sim/PLL.vo"] 7 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL.spd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL/PLL_0002.qip: -------------------------------------------------------------------------------- 1 | set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 2 | 3 | set_instance_assignment -name PLL_AUTO_RESET OFF -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 4 | set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*PLL_0002*|altera_pll:altera_pll_i*|*" 5 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL_sim.f: -------------------------------------------------------------------------------- 1 | PLL_sim/PLL.vo 2 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL_sim/cadence/cds.lib: -------------------------------------------------------------------------------- 1 | 2 | DEFINE std $CDS_ROOT/tools/inca/files/STD/ 3 | DEFINE synopsys $CDS_ROOT/tools/inca/files/SYNOPSYS/ 4 | DEFINE ieee $CDS_ROOT/tools/inca/files/IEEE/ 5 | DEFINE ambit $CDS_ROOT/tools/inca/files/AMBIT/ 6 | DEFINE vital_memory $CDS_ROOT/tools/inca/files/VITAL_MEMORY/ 7 | DEFINE ncutils $CDS_ROOT/tools/inca/files/NCUTILS/ 8 | DEFINE ncinternal $CDS_ROOT/tools/inca/files/NCINTERNAL/ 9 | DEFINE ncmodels $CDS_ROOT/tools/inca/files/NCMODELS/ 10 | DEFINE cds_assertions $CDS_ROOT/tools/inca/files/CDS_ASSERTIONS/ 11 | DEFINE work ./libraries/work/ 12 | DEFINE altera_ver ./libraries/altera_ver/ 13 | DEFINE lpm_ver ./libraries/lpm_ver/ 14 | DEFINE sgate_ver ./libraries/sgate_ver/ 15 | DEFINE altera_mf_ver ./libraries/altera_mf_ver/ 16 | DEFINE altera_lnsim_ver ./libraries/altera_lnsim_ver/ 17 | DEFINE cyclonev_ver ./libraries/cyclonev_ver/ 18 | DEFINE cyclonev_hssi_ver ./libraries/cyclonev_hssi_ver/ 19 | DEFINE cyclonev_pcie_hip_ver ./libraries/cyclonev_pcie_hip_ver/ 20 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL_sim/cadence/hdl.var: -------------------------------------------------------------------------------- 1 | 2 | DEFINE WORK work 3 | -------------------------------------------------------------------------------- /Project/SourceCode/PLL_sim/synopsys/vcsmx/synopsys_sim.setup: -------------------------------------------------------------------------------- 1 | 2 | WORK > DEFAULT 3 | DEFAULT: ./libraries/work/ 4 | work: ./libraries/work/ 5 | altera_ver: ./libraries/altera_ver/ 6 | lpm_ver: ./libraries/lpm_ver/ 7 | sgate_ver: ./libraries/sgate_ver/ 8 | altera_mf_ver: ./libraries/altera_mf_ver/ 9 | altera_lnsim_ver: ./libraries/altera_lnsim_ver/ 10 | cyclonev_ver: ./libraries/cyclonev_ver/ 11 | cyclonev_hssi_ver: ./libraries/cyclonev_hssi_ver/ 12 | cyclonev_pcie_hip_ver: ./libraries/cyclonev_pcie_hip_ver/ 13 | LIBRARY_SCAN = TRUE 14 | -------------------------------------------------------------------------------- /Project/SourceCode/Quartus/ImageRecog.qpf: -------------------------------------------------------------------------------- 1 | DATE = "00:49:52 March 09, 2023" 2 | QUARTUS_VERSION = "15.1.0" 3 | 4 | # Revisions 5 | 6 | PROJECT_REVISION = "ImageRecog" 7 | -------------------------------------------------------------------------------- /Project/SourceCode/Quartus/ram_2p.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram_2p.v"] 5 | -------------------------------------------------------------------------------- /Project/SourceCode/Quartus/work/_lib.qdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/SourceCode/Quartus/work/_lib.qdb -------------------------------------------------------------------------------- /Project/SourceCode/Quartus/work/_vmake: -------------------------------------------------------------------------------- 1 | m255 2 | K4 3 | z0 4 | cModel Technology 5 | -------------------------------------------------------------------------------- /Project/SourceCode/RAW2GRAY.v: -------------------------------------------------------------------------------- 1 | module RAW2GRAY(oGrey, 2 | oDVAL, 3 | iX_Cont, 4 | iY_Cont, 5 | iDATA, 6 | iDVAL, 7 | iCLK, 8 | iRST, 9 | oEdge 10 | ); 11 | 12 | input [10:0] iX_Cont; 13 | input [10:0] iY_Cont; 14 | input [11:0] iDATA; 15 | input iDVAL; 16 | input iCLK; 17 | input iRST; 18 | output [11:0] oGrey; 19 | output oDVAL; 20 | output oEdge; 21 | wire [11:0] mDATA_0; 22 | wire [11:0] mDATA_1; 23 | wire [12:0] mDATA_sum; 24 | reg [12:0] mDATA_d; 25 | reg [13:0] mCCD_G; 26 | reg mDVAL; 27 | reg mEdge; 28 | 29 | assign oGrey = mCCD_G[13:2]; 30 | assign oDVAL = mDVAL; 31 | assign oEdge = mEdge; 32 | 33 | assign mDATA_sum = (mDATA_0+mDATA_1); 34 | 35 | Line_Buffer1 u0 ( .clken(iDVAL), 36 | .clock(iCLK), 37 | .shiftin(iDATA), 38 | .taps0x(mDATA_1), 39 | .taps1x(mDATA_0) ); 40 | 41 | always@(posedge iCLK or negedge iRST) 42 | begin 43 | if(!iRST) 44 | begin 45 | mCCD_G <= 0; 46 | mDATA_d <= 0; 47 | mDVAL <= 0; 48 | end 49 | else 50 | begin 51 | mDATA_d <= mDATA_sum; 52 | mDVAL <= {iY_Cont[0]|iX_Cont[0]} ? 1'b0 : iDVAL; 53 | mEdge <= (iY_Cont==0||iX_Cont==0||iY_Cont==11'd479||iX_Cont==11'd639); 54 | mCCD_G <= mDATA_sum+mDATA_d; 55 | end 56 | end 57 | 58 | endmodule 59 | 60 | 61 | -------------------------------------------------------------------------------- /Project/SourceCode/Sdram_Control/Sdram_Params.h: -------------------------------------------------------------------------------- 1 | // Address Space Parameters 2 | 3 | `define ROWSTART 8 4 | `define ROWSIZE 12 5 | `define COLSTART 0 6 | `define COLSIZE 8 7 | `define BANKSTART 20 8 | `define BANKSIZE 2 9 | 10 | // Address and Data Bus Sizes 11 | 12 | `define ASIZE 23 // total address width of the SDRAM 13 | `define DSIZE 16 // Width of data bus to SDRAMS 14 | 15 | 16 | //parameter INIT_PER = 100; // For Simulation 17 | 18 | // Controller Parameter 19 | //////////// 133 MHz /////////////// 20 | /* 21 | parameter INIT_PER = 32000; 22 | parameter REF_PER = 1536; 23 | parameter SC_CL = 3; 24 | parameter SC_RCD = 3; 25 | parameter SC_RRD = 7; 26 | parameter SC_PM = 1; 27 | parameter SC_BL = 1; 28 | */ 29 | /////////////////////////////////////// 30 | //////////// 100 MHz /////////////// 31 | parameter INIT_PER = 24000; 32 | parameter REF_PER = 1024; 33 | parameter SC_CL = 3; 34 | parameter SC_RCD = 3; 35 | parameter SC_RRD = 7; 36 | parameter SC_PM = 1; 37 | parameter SC_BL = 1; 38 | /////////////////////////////////////// 39 | //////////// 50 MHz /////////////// 40 | /* 41 | parameter INIT_PER = 12000; 42 | parameter REF_PER = 512; 43 | parameter SC_CL = 3; 44 | parameter SC_RCD = 3; 45 | parameter SC_RRD = 7; 46 | parameter SC_PM = 1; 47 | parameter SC_BL = 1; 48 | */ 49 | /////////////////////////////////////// 50 | 51 | // SDRAM Parameter 52 | parameter SDR_BL = (SC_PM == 1) ? 3'b111 : 53 | (SC_BL == 1) ? 3'b000 : 54 | (SC_BL == 2) ? 3'b001 : 55 | (SC_BL == 4) ? 3'b010 : 3'b011; 56 | parameter SDR_BT = 1'b0; // 1'b0 : Sequential 1'b1 : Interteave 57 | parameter SDR_CL = (SC_CL == 2) ? 3'b10 : 3'b11; -------------------------------------------------------------------------------- /Project/SourceCode/Sdram_Control/Sdram_RD_FIFO.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "FIFO" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Sdram_RD_FIFO.v"] 5 | -------------------------------------------------------------------------------- /Project/SourceCode/Sdram_Control/Sdram_WR_FIFO.qip: -------------------------------------------------------------------------------- 1 | set_global_assignment -name IP_TOOL_NAME "FIFO" 2 | set_global_assignment -name IP_TOOL_VERSION "21.1" 3 | set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" 4 | set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "Sdram_WR_FIFO.v"] 5 | -------------------------------------------------------------------------------- /Project/SourceCode/common_params.inc: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////// 3 | // Create defines for ALU functions // 4 | ///////////////////////////////////// 5 | localparam ADD = 3'b000; 6 | localparam SUB = 3'b001; 7 | localparam AND = 3'b010; 8 | localparam NOR = 3'b011; 9 | localparam SLL = 3'b100; 10 | localparam SRL = 3'b101; 11 | localparam SRA = 3'b110; 12 | localparam LHB = 3'b111; 13 | 14 | //////////////////////////////////////////////// 15 | // Create defines for advanced ALU functions // 16 | ////////////////////////////////////////////// 17 | localparam MUL = 3'b000; 18 | localparam UMUL = 3'b001; 19 | localparam ADDF = 3'b010; 20 | localparam SUBF = 3'b011; 21 | localparam MULF = 3'b100; 22 | localparam ITF = 3'b101; 23 | localparam FTI = 3'b110; 24 | 25 | ////////////////////////////////////////// 26 | // Create defines for Opcode encodings // 27 | //////////////////////////////////////// 28 | localparam ADDi = 5'b00000; 29 | localparam ADDZi = 5'b00001; 30 | localparam SUBi = 5'b00010; 31 | localparam ANDi = 5'b00011; 32 | localparam NORi = 5'b00100; 33 | localparam SLLi = 5'b00101; 34 | localparam SRLi = 5'b00110; 35 | localparam SRAi = 5'b00111; 36 | localparam LWi = 5'b01000; 37 | localparam SWi = 5'b01001; 38 | localparam LHBi = 5'b01010; 39 | localparam LLBi = 5'b01011; 40 | localparam BRi = 5'b01100; 41 | localparam JALi = 5'b01101; 42 | localparam JRi = 5'b01110; 43 | localparam LWIi = 5'b10000; 44 | localparam PUSHi = 5'b10010; 45 | localparam POPi = 5'b10011; 46 | localparam ADDIi = 5'b10100; 47 | localparam SUBIi = 5'b10101; 48 | localparam MULi = 5'b11000; 49 | localparam UMULi = 5'b11001; 50 | localparam ADDFi = 5'b11010; 51 | localparam SUBFi = 5'b11011; 52 | localparam MULFi = 5'b11100; 53 | localparam ITFi = 5'b11101; 54 | localparam FTIi = 5'b11110; 55 | localparam HLTi = 5'b11111; 56 | 57 | //////////////////////////////// 58 | // Encodings for src0 select // 59 | ////////////////////////////// 60 | localparam RF2SRC0 = 2'b00; 61 | localparam IMM_BR2SRC0 = 2'b01; // 12-bit SE for branch target 62 | localparam IMM_JMP2SRC0 = 2'b10; // 12-bit SE for jump target 63 | localparam IMM2SRC0 = 2'b11; // 8-bit SE Address immediate for LW/SW 64 | 65 | //////////////////////////////// 66 | // Encodings for src1 select // 67 | ////////////////////////////// 68 | localparam RF2SRC1 = 2'b00; 69 | localparam IMM2SRC1 = 2'b01; // 16-bit data immediate for LLB/LHB 70 | localparam NPC2SRC1 = 2'b10; // nxt_pc to src1 for JAL instruction 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Project/SourceCode/compress_request_system.sv: -------------------------------------------------------------------------------- 1 | module compress_request_system( 2 | input clk, 3 | input rst_n, 4 | input [7:0] uncompress_addr_x, 5 | input [7:0] uncompress_addr_y, 6 | input we, 7 | input compress_wdata, 8 | input pause, 9 | output reg compress_req, 10 | output compress_start 11 | ); 12 | 13 | // This signal indicates the process of compressing the image. 1 indicates the compression started and is in process, 0 indicates that the compress is finished/idle. 14 | reg compress_proc; 15 | 16 | // Compressor snapshot request system 17 | always @(negedge clk, negedge rst_n) 18 | if(!rst_n) 19 | compress_req <= 1'b0; 20 | else if (compress_proc && uncompress_addr_x == 223 && uncompress_addr_y == 223) 21 | compress_req <= 1'b0; 22 | else if (we) 23 | compress_req <= compress_wdata; 24 | 25 | always @(negedge clk, negedge rst_n) 26 | if(!rst_n) 27 | compress_proc <= 1'b0; 28 | else if (compress_start) 29 | compress_proc <= 1'b1; 30 | else if (compress_proc && uncompress_addr_x == 223 && uncompress_addr_y == 223) 31 | compress_proc <=1'b0; 32 | 33 | assign compress_start = ((compress_req | !pause) && uncompress_addr_x == 8'h0 && uncompress_addr_y == 8'h0); 34 | 35 | endmodule 36 | -------------------------------------------------------------------------------- /Project/SourceCode/cpu_tb.sv: -------------------------------------------------------------------------------- 1 | module cpu_tb(); 2 | 3 | reg clk,rst_n; 4 | wire TX, RX; 5 | assign TX = 1'hz; 6 | assign RX = 1'hz; 7 | ////////////////////// 8 | // Instantiate CPU // 9 | //////////////////// 10 | cpu iCPU(.clk(clk), .rst_n(rst_n),.rdata(),.addr(),.re(),.we(),.wdata()); 11 | initial begin 12 | clk = 0; 13 | rst_n = 0; 14 | #2 rst_n = 1; 15 | #300; 16 | if(iCPU.iPC.pc <= 176 && iCPU.iPC.pc >= 173) begin 17 | $display("tests passed!"); 18 | $finish(); 19 | end 20 | else begin 21 | $error("tests failed!"); 22 | $finish(); 23 | end 24 | 25 | end 26 | 27 | always 28 | #1 clk = ~clk; 29 | 30 | endmodule 31 | -------------------------------------------------------------------------------- /Project/SourceCode/data_mem.v: -------------------------------------------------------------------------------- 1 | module DM(clk,addr,re,we,wrt_data,rd_data); 2 | 3 | ///////////////////////////////////////////////////////// 4 | // Data memory. Single ported, can read or write but // 5 | // not both in a single cycle. Precharge on clock // 6 | // high, read/write on clock low. // 7 | ///////////////////////////////////////////////////// 8 | input clk; 9 | input [12:0] addr; 10 | input re; // asserted when instruction read desired 11 | input we; // asserted when write desired 12 | input [31:0] wrt_data; // data to be written 13 | 14 | output reg [31:0] rd_data; // output of data memory 15 | 16 | reg [31:0]data_mem[0:8191]; // 8K*32 data memory 17 | 18 | ///////////////////////////////////////// 19 | // Read is synchronous on negedge clk // 20 | /////////////////////////////////////// 21 | always @(negedge clk) 22 | if (re && ~we) 23 | rd_data <= data_mem[addr]; 24 | 25 | ///////////////////////////////////////////////// 26 | // Model write, data is written on clock fall // 27 | /////////////////////////////////////////////// 28 | always @(negedge clk) 29 | if (we && ~re) 30 | data_mem[addr] <= wrt_data; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /Project/SourceCode/dst_mux.v: -------------------------------------------------------------------------------- 1 | module dst_mux(clk,dm_re_EX_DM, im_re_EX_DM, stack_EX_DM, dm_rd_data_EX_DM,stack_pop_EX_DM, pc_EX_DM,dst_EX_DM,dst_ext_EX_DM, rf_w_data_DM_WB, im_rd_data_EX_DM, jmp_imm_EX_DM,ext_alu_EX_DM); 2 | //////////////////////////////////////////////////////////////////////// 3 | // Simple 2:1 mux determining if ALU or DM is source for write to RF // 4 | ////////////////////////////////////////////////////////////////////// 5 | input clk; 6 | input dm_re_EX_DM; 7 | input im_re_EX_DM; // instrction read enable from ex stage 8 | input stack_pop_EX_DM; // pop instruction from stack_pop 9 | input jmp_imm_EX_DM; 10 | input ext_alu_EX_DM; // input from ID to choose external ALU 11 | input [31:0] dm_rd_data_EX_DM; // input from DM 12 | input [31:0] im_rd_data_EX_DM; // input from IM 13 | input [31:0] pc_EX_DM; // from PC for JAL saving to R15 14 | input [31:0] dst_EX_DM; // input from ALU 15 | input [31:0] dst_ext_EX_DM; // input from ext ALU 16 | input [31:0] stack_EX_DM; // input from stack 17 | 18 | output reg[31:0] rf_w_data_DM_WB; // output to be written to RF 19 | 20 | always @(posedge clk) 21 | if (dm_re_EX_DM) 22 | rf_w_data_DM_WB <= dm_rd_data_EX_DM; 23 | else if (im_re_EX_DM) 24 | rf_w_data_DM_WB <= im_rd_data_EX_DM; 25 | else if (jmp_imm_EX_DM) 26 | rf_w_data_DM_WB <= pc_EX_DM; 27 | else if (ext_alu_EX_DM) 28 | rf_w_data_DM_WB <= dst_ext_EX_DM; 29 | else if (stack_pop_EX_DM) 30 | rf_w_data_DM_WB <= stack_EX_DM; 31 | else 32 | rf_w_data_DM_WB <= dst_EX_DM; 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /Project/SourceCode/dualPort32x32.sv: -------------------------------------------------------------------------------- 1 | module dualPort32x32(clk,we,re,waddr,raddr,wdata,rdata); 2 | 3 | input clk; // system clock 4 | input we; // write enable 5 | input re; // read enable 6 | input [4:0] waddr; // write address 7 | input [4:0] raddr; // read address 8 | input [31:0] wdata; // data to write 9 | output reg [31:0] rdata; // read data output 10 | 11 | reg [31:0] mem [31:0]; // 32 by 32 SRAM block 12 | 13 | // negedge triggered memory 14 | always @(negedge clk) begin 15 | if(we) 16 | mem[waddr] <= wdata; 17 | if(re) 18 | rdata <= mem[raddr]; 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /Project/SourceCode/extended_ALU.sv: -------------------------------------------------------------------------------- 1 | module extended_ALU(clk, src1, src0, func, dst_EX_DM, ov, zr, neg); 2 | // Encoding of func[2:0] is as follows: // 3 | // 000 ==> MUL 4 | // 001 ==> UMUL 5 | // 010 ==> ADDF 6 | // 011 ==> SUBF 7 | // 100 ==> MULF 8 | // 101 ==> ITF 9 | // 110 ==> FTI 10 | // 111 ==> undefined 11 | 12 | `include "common_params.inc" 13 | 14 | input clk; 15 | input [31:0] src1, src0; 16 | input [2:0] func; // selects function to perform 17 | output reg [31:0] dst_EX_DM; 18 | output ov, zr, neg; 19 | 20 | logic [31:0] ifadd_OUT, ifmul_OUT, iftoi_OUT, iitof_OUT, iimul_OUT; 21 | 22 | logic [31:0] OUT; 23 | 24 | /////////////////////// 25 | // compute modules // 26 | ///////////////////// 27 | 28 | FP_adder ifadd( 29 | .A(src1), 30 | .B(func==SUBF ? {~src0[31], src0[30:0]} : src0), // flip second operand if doing A - B 31 | .out(ifadd_OUT) 32 | ); 33 | 34 | FP_mul ifmul( 35 | .A(src1), 36 | .B(src0), 37 | .OUT(ifmul_OUT) 38 | ); 39 | 40 | float_to_signed_int iftoi( 41 | .FP_val(src1), 42 | .signed_int_val(iftoi_OUT) 43 | ); 44 | 45 | signed_int_to_float iitof( 46 | .signed_int_val(src1), 47 | .FP_val(iitof_OUT) 48 | ); 49 | 50 | int_mul_16by16 iimul( 51 | .A(src1[15:0]), 52 | .B(src0[15:0]), 53 | .sign(~func[0]), // 0 ==> MUL 1 ==> UMUL 54 | .OUT(iimul_OUT) 55 | ); 56 | 57 | /////////////////////////////////// 58 | // Multiplexing function of ALU // 59 | ///////////////////////////////// 60 | assign OUT = (func==MUL || func==UMUL) ? iimul_OUT : 61 | (func==ADDF || func==SUBF) ? ifadd_OUT : 62 | (func==MULF) ? ifmul_OUT : 63 | (func==ITF) ? iitof_OUT : 64 | (func==FTI) ? iftoi_OUT : 65 | 32'hDEADDEAD; // undefined behavior 66 | 67 | ///////////////////////// 68 | // Set flag variables // 69 | /////////////////////// 70 | // these 7 instructions can NEVER overflow (FP operations are saturating following their own rules) 71 | assign ov = 1'b0; 72 | 73 | // assign zero flag according to if output is in normal format or FP format 74 | assign zr = (func==MUL || func==UMUL || func==FTI) ? ~|OUT : ~|OUT[30:0]; 75 | 76 | // assign neg flag according to if output is signed or unsigned 77 | assign neg = (func==UMUL) ? 1'b0 : OUT[31]; 78 | 79 | ////////////////////////// 80 | // Flop the ALU result // 81 | //////////////////////// 82 | always @(posedge clk) 83 | dst_EX_DM <= OUT; 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /Project/SourceCode/fifo.sv: -------------------------------------------------------------------------------- 1 | // A fifo queue that allows read and write at same time 2 | module fifo( 3 | input clk, // 50MHz clk 4 | input rst_n, // asynch active low reset 5 | input w_en, // write enable 6 | input r_en, // read enable 7 | input [7:0] in_data, // data to be stored in queue 8 | output q_full, // indicates queue is full 9 | output q_empty, // indicates queue is empty 10 | output [7:0] out_data, // data to be read in queue 11 | output [3:0] contain_num // Number of used entires in the queue 12 | ); 13 | 14 | ///////////////////////////// 15 | // Declare reg and wires // 16 | /////////////////////////// 17 | reg [3:0] head_ptr, tail_ptr; // Insert into head, pop from tail 18 | reg [7:0] buffer [0:7]; // 8 entry buffer with 8bits wide data 19 | 20 | // When all 8 entries are filled, the lower 3 bits of the pointer will be same, but the highest bit will be different 21 | assign q_full = tail_ptr[2:0] == head_ptr[2:0] && tail_ptr[3] == ~head_ptr[3]; 22 | // When head ptr and tail ptr are same, the queue is empty 23 | assign q_empty = tail_ptr == head_ptr; 24 | // Number of used/filled entry in the queue 25 | assign contain_num = head_ptr - tail_ptr; 26 | 27 | ///////////////////////////////// 28 | // Read data from the buffer // 29 | /////////////////////////////// 30 | assign out_data = buffer[tail_ptr[2:0]]; //Constantly output the data from the tail_ptr 31 | 32 | /////////////////////////////////// 33 | // Write data into the buffer // 34 | ///////////////////////////////// 35 | always_ff @(posedge clk) 36 | if (w_en && !q_full) 37 | buffer[head_ptr[2:0]] <= in_data; 38 | 39 | /////////////////////////////// 40 | // Tail ptr control logic // 41 | ///////////////////////////// 42 | always_ff @(posedge clk, negedge rst_n) 43 | if (!rst_n) 44 | tail_ptr <= 4'h0; 45 | else if (r_en && !q_empty) // Increment tail_ptr when read enabled and queue is not empty 46 | tail_ptr <= tail_ptr + 4'h1; // Increment tail_ptr == pop an entry from the queue 47 | 48 | /////////////////////////////// 49 | // Head ptr control logic // 50 | ///////////////////////////// 51 | always_ff @(posedge clk, negedge rst_n) 52 | if (!rst_n) 53 | head_ptr <= 4'h0; 54 | else if (w_en && !q_full) // Increment head ptr when write enabled and queue is not full 55 | head_ptr <= head_ptr + 4'h1; 56 | 57 | endmodule 58 | -------------------------------------------------------------------------------- /Project/SourceCode/float_to_signed_int.sv: -------------------------------------------------------------------------------- 1 | module float_to_signed_int(FP_val, signed_int_val); 2 | 3 | input [31:0] FP_val; // input is 32 bit float 4 | output signed [31:0] signed_int_val; // output is 32 bit signed int 5 | 6 | logic [22:0] M; // mantissa 7 | logic [7:0] E; // exponent 8 | 9 | logic [30:0] abs_int; // unsigned value of (1.M) * 2^(E-127) 10 | 11 | assign M = FP_val[22:0]; 12 | assign E = FP_val[30:23]; 13 | 14 | // calculate the absolute value of the integer, choosing correct shift direction according to E 15 | assign abs_int = E >= 8'd150 ? {8'h00, 1'b1, M} << (E - 8'd150) : {8'h00, 1'b1, M} >> (8'd150 - E); 16 | 17 | // convert abs_int to signed_int_val with saturation/zeroing logic 18 | assign signed_int_val = E >= 8'd182 ? ((FP_val[31]) ? 32'h80000000 : 32'h7FFFFFFF) : // if E too large, saturate 19 | E < 8'd127 ? 32'h00000000 : // if E too small, zero 20 | (FP_val[31]) ? {1'b1, (~abs_int + 31'd00000001)} : {1'b0, abs_int}; // if neither of the extremes, output according to sign 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Project/SourceCode/image_mem.sv: -------------------------------------------------------------------------------- 1 | module image_mem(clk,we,waddr,wdata,raddr,rdata); 2 | 3 | input clk; 4 | input we; 5 | input [9:0] waddr; 6 | input [7:0] wdata; 7 | input [9:0] raddr; 8 | output reg [7:0] rdata; 9 | 10 | reg [7:0]mem[0:1023]; // for CNN padded image is 32 by 32 11 | 12 | always @(negedge clk) begin 13 | if (we) 14 | mem[waddr] <= wdata < 50 ? 0 :wdata; 15 | rdata <= mem[raddr]; 16 | end 17 | 18 | endmodule 19 | -------------------------------------------------------------------------------- /Project/SourceCode/instr_mem.v: -------------------------------------------------------------------------------- 1 | module IM(clk,addr,rd_en,instr); 2 | 3 | input clk; 4 | input [13:0] addr; 5 | input rd_en; // asserted when instruction read desired 6 | 7 | output reg [31:0] instr; // output of insturction memory 8 | 9 | reg [31:0]instr_mem[0:1023]; // 1K*32 instruction memory 10 | 11 | /////////////////////////////////// 12 | // Memory is flopped on negedge // 13 | ///////////////////////////////// 14 | always @(negedge clk) 15 | if (rd_en) 16 | instr <= instr_mem[addr]; 17 | 18 | initial begin 19 | $readmemh("../instr.hex",instr_mem); 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Project/SourceCode/int_mul_16by16.sv: -------------------------------------------------------------------------------- 1 | module int_mul_16by16(A, B, sign, OUT); 2 | 3 | input [15:0] A; // 16 bit integer input 4 | input [15:0] B; // 16 bit integer input 5 | input sign; // signed multiply when set, unsigned multiply when unsigned 6 | output [31:0] OUT; // the product of A*B 7 | 8 | logic signed [16:0] A_eff, B_eff; 9 | logic signed [33:0] product; 10 | 11 | assign A_eff = {sign ? A[15] : 1'b0, A}; 12 | assign B_eff = {sign ? B[15] : 1'b0, B}; 13 | 14 | assign product = A_eff * B_eff; 15 | 16 | assign OUT = product[31:0]; 17 | 18 | endmodule -------------------------------------------------------------------------------- /Project/SourceCode/left_shifter.sv: -------------------------------------------------------------------------------- 1 | // Another self-explaining module 2 | module left_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {In[22:0],1'b0} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {shft_stg1[21:0],2'b0} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {shft_stg2[19:0],4'b0} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {shft_stg3[15:0],8'b0} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {shft_stg4[7:0],16'b0} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/SourceCode/rf.v: -------------------------------------------------------------------------------- 1 | module rf(clk,p0_addr,p1_addr,p0,p1,re0,re1,dst_addr,dst,we,hlt); 2 | ////////////////////////////////////////////////////////////////// 3 | // Triple ported register file. Two read ports (p0 & p1), and // 4 | // one write port (dst). Data is written on clock high, and // 5 | // read on clock low ////////////////////////////////////////// 6 | ////////////////////// 7 | 8 | input clk; 9 | input [4:0] p0_addr, p1_addr; // two read port addresses 10 | input re0,re1; // read enables (power not functionality) 11 | input [4:0] dst_addr; // write address 12 | input [31:0] dst; // dst bus 13 | input we; // write enable 14 | input hlt; // not a functional input. Used to dump register contents when 15 | // test is halted. (No longer used) 16 | 17 | output [31:0] p0,p1; // output read ports 18 | 19 | wire r0_bypass, r1_bypass; // RF bypass 20 | wire [31:0] p0_raw, p1_raw; // raw read output from SRAM 21 | 22 | ///////////////////////////////////////////////////////////////////// 23 | // Instantiate two dualport memory to create a tripple port rf // 24 | // Always write same data to both sram instance at the same time // 25 | ////////////////////////////////////////////////////////////////// 26 | dualPort32x32 sram0( 27 | .clk(clk), 28 | .we(we), 29 | .re(re0), 30 | .waddr(dst_addr), 31 | .raddr(p0_addr), 32 | .wdata(dst), 33 | .rdata(p0_raw) 34 | ); 35 | dualPort32x32 sram1( 36 | .clk(clk), 37 | .we(we), 38 | .re(re1), 39 | .waddr(dst_addr), 40 | .raddr(p1_addr), 41 | .wdata(dst), 42 | .rdata(p1_raw) 43 | ); 44 | 45 | // Bypass if any read register is the same as the write register and both re and we are high 46 | assign r0_bypass = ~|(p0_addr ^ dst_addr) & re0 & we; 47 | assign r1_bypass = ~|(p1_addr ^ dst_addr) & re1 & we; 48 | 49 | // R0 always stay at 32'h0000_0000 50 | assign p0 = ~|p0_addr ? 32'h0000_0000 : (r0_bypass ? dst : p0_raw); 51 | assign p1 = ~|p1_addr ? 32'h0000_0000 : (r1_bypass ? dst : p1_raw); 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /Project/SourceCode/right_shifter.sv: -------------------------------------------------------------------------------- 1 | // A self-explaining module 2 | module right_shifter(In, ShAmt, Out); 3 | 4 | input [23:0] In; // Input operand 5 | input [4:0] ShAmt; // Amount to shift/rotate 6 | output [23:0] Out; // Result of shift/rotate 7 | 8 | wire [23:0] shft_stg1, shft_stg2, shft_stg3, shft_stg4; 9 | 10 | assign shft_stg1 = ShAmt[0] ? {1'b0,In[23:1]} : {In}; 11 | assign shft_stg2 = ShAmt[1] ? {2'b0,shft_stg1[23:2]} : {shft_stg1}; 12 | assign shft_stg3 = ShAmt[2] ? {4'b0,shft_stg2[23:4]} : {shft_stg2}; 13 | assign shft_stg4 = ShAmt[3] ? {8'b0,shft_stg3[23:8]} : {shft_stg3}; 14 | assign Out = ShAmt[4] ? {16'b0,shft_stg4[23:16]} : {shft_stg4}; 15 | 16 | endmodule -------------------------------------------------------------------------------- /Project/SourceCode/rst_synch.v: -------------------------------------------------------------------------------- 1 | module rst_synch(clk,RST_n,pll_locked,rst_n); 2 | 3 | input clk; // 50MHz clock 4 | input RST_n; // non synched reset from push button 5 | input pll_locked; // don't deassert reset till PLL is locked 6 | output reg rst_n; // synched on deassert to negedge of clock 7 | 8 | reg q1; 9 | 10 | //////////////////////////////////////////////// 11 | // rst_n is asserted asynch, but deasserted // 12 | // syncronized to negedge clock. Two flops // 13 | // are used for metastability purposes. // 14 | //////////////////////////////////////////// 15 | always @(negedge clk, negedge RST_n) 16 | if (!RST_n) 17 | begin 18 | q1 <= 1'b0; 19 | rst_n <= 1'b0; 20 | end 21 | else 22 | begin 23 | q1 <= pll_locked; 24 | rst_n <= q1; 25 | end 26 | 27 | endmodule -------------------------------------------------------------------------------- /Project/SourceCode/stack.sv: -------------------------------------------------------------------------------- 1 | // This is a 32x1024 stack for PUSH and POP instructions 2 | // Only one operation can be performed at a time 3 | module stack(clk, rst_n, push, pop, wdata,stack_EX_DM); 4 | input clk; // system clock 5 | input rst_n; // active low async reset 6 | input push; // write into stack 7 | input pop; // pop from stack 8 | input [31:0] wdata; // data to write 9 | output reg [31:0] stack_EX_DM; // flopped stack read result 10 | reg [31:0] rdata; // read data output 11 | 12 | reg [31:0] mem [1023:0]; // 32 by 1024 SRAM block 13 | 14 | reg [10:0] addr; // 10 bit address for stack pointer, 1 extra bit for 1024th data 15 | wire full, empty; // signals to control the edge behavior 16 | 17 | assign rdata = mem[addr]; 18 | assign full = addr == 11'h400; 19 | assign empty = addr == 10'h000; 20 | 21 | // negedge triggered memory 22 | always @(negedge clk) begin 23 | if(push & ~full) 24 | mem[addr] <= wdata; 25 | end 26 | 27 | always @(negedge clk, negedge rst_n) begin 28 | if (!rst_n) 29 | addr <= 11'h000; 30 | else if (push & ~full) 31 | addr <= addr + 11'h001; 32 | else if (pop & ~empty) 33 | addr <= addr - 11'h001; 34 | end 35 | 36 | ////////////////////////// 37 | // Flop the ALU result // 38 | //////////////////////// 39 | always @(posedge clk) 40 | stack_EX_DM <= rdata; 41 | endmodule -------------------------------------------------------------------------------- /Project/SourceCode/test/FTI.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test FTI basic function ## 3 | ############################ 4 | LLB R1, 0x0000 5 | LHB R1, 0xBF80 # -1f 6 | FTI R2, R1 # should be 0xFFFFFFFF 7 | LLB R3, 0xFFFF 8 | SUB R3, R2, R3 9 | B NEQ, L_FAIL 10 | 11 | ############################ 12 | ##Test FTI basic function ## 13 | ############################ 14 | LLB R1, 0x1000 15 | LHB R1, 0x4480 # 1024.5f 16 | FTI R2, R1 # should be 0x00000400 17 | LLB R3, 0x0400 # 1024d 18 | SUB R3, R2, R3 19 | B NEQ, L_FAIL 20 | B UNCOND, L_PASS 21 | 22 | 23 | ######################### 24 | ##Pass routine at 0xAD ## 25 | ######################### 26 | MEM 0x00AD 27 | L_PASS: 28 | B UNCOND, L_PASS 29 | 30 | ######################### 31 | ##Fail routine at 0xDD ## 32 | ######################### 33 | MEM 0x00DD 34 | L_FAIL: 35 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/ITF.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test ITF basic function ## 3 | ############################ 4 | LLB R1, 0x04D2 # 1234d 5 | ITF R2, R1 # should be 0x449a4000 6 | LLB R3, 0x4000 7 | LHB R3, 0x449a 8 | SUBF R3, R2, R3 9 | B NEQ, L_FAIL 10 | 11 | ############################ 12 | ##Test ITF basic function ## 13 | ############################ 14 | LLB R1, 0xEF1F # -4321d 15 | ITF R2, R1 # should be 0xc5870800 16 | LLB R3, 0x0800 17 | LHB R3, 0xC587 18 | SUBF R3, R2, R3 19 | B NEQ, L_FAIL 20 | B UNCOND, L_PASS 21 | 22 | 23 | ######################### 24 | ##Pass routine at 0xAD ## 25 | ######################### 26 | MEM 0x00AD 27 | L_PASS: 28 | B UNCOND, L_PASS 29 | 30 | ######################### 31 | ##Fail routine at 0xDD ## 32 | ######################### 33 | MEM 0x00DD 34 | L_FAIL: 35 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/addf.asm: -------------------------------------------------------------------------------- 1 | ################################### 2 | ##Test ADDF does not set ov flag ## 3 | ################################### 4 | LLB R1, 0x0000 5 | LHB R1, 0x7F80 # positive infinite 6 | ADDF R2, R1, R1 # results in pos_inf 7 | B OVFL, L_FAIL # branch to fail routine if overflow 8 | 9 | ############################ 10 | ##Test ADDF sets neg flag ## 11 | ############################ 12 | LLB R1, 0x0000 13 | LHB R1, 0xC000 14 | LLB R2, 0x0000 15 | LHB R2, 0x3FA0 16 | ADDF R2, R1, R2 # -2 + 1.25 = -0.75 17 | B GTE, L_FAIL # branch to fail if negative flag is not set 18 | 19 | ########################## 20 | ##Test MUL sets zr flag ## 21 | ########################## 22 | LLB R1, 0x0000 23 | LLB R2, 0x0000 24 | LHB R2, 0x8000 25 | ADDF R2, R1, R2 # 0 + (-0) = -0 26 | B NEQ, L_FAIL 27 | B UNCOND, L_PASS 28 | 29 | ######################### 30 | ##Pass routine at 0xAD ## 31 | ######################### 32 | MEM 0x00AD 33 | L_PASS: 34 | B UNCOND, L_PASS 35 | 36 | ######################### 37 | ##Fail routine at 0xDD ## 38 | ######################### 39 | MEM 0x00DD 40 | L_FAIL: 41 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/and.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test SUBi basic function ## 3 | ############################ 4 | ## subtracting two positive numbers 5 | ## with correct output 6 | LLB R1, 0x6666 # R1 contains 0x00006666 7 | LLB R2, 0x6060 # R2 contains 0x00006060 8 | AND R3, R1, R2 # R3 should be 0x00006060 9 | LLB R4, 0x6060 # R4 contains 0x00006060 10 | SUB R4, R3, R4 # compare R3 to known right answer 11 | B NEQ, L_FAIL # branch to fail routine 12 | 13 | ################################## 14 | ##Test that AND sets carry flag ## 15 | ################################## 16 | ## should set overflow 17 | LLB R1, 0x0000 # R1 contains 0x00000000 18 | LHB R1, 0x0000 # R1 contains 0x00000000 19 | LLB R2, 0x0000 # R2 contains 0x00000000 20 | LHB R2, 0x0000 # R2 contains 0x00000000 21 | AND R3, R1, R2 # R3 should be 0x00000000 22 | B EQ, L_PASS # branch to pass routine if overflow 23 | B NEQ, L_FAIL # branch to fail routine 24 | 25 | ######################### 26 | ##Pass routine at 0xAD ## 27 | ######################### 28 | MEM 0x00AD 29 | L_PASS: 30 | B UNCOND, L_PASS 31 | 32 | ######################### 33 | ##Fail routine at 0xDD ## 34 | ######################### 35 | MEM 0x00DD 36 | L_FAIL: 37 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/branch.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test BNEQ basic function ## 3 | ############################ 4 | LLB R1, 0x5555 # R1 contains 0x00005555 5 | LLB R2, 0x1111 # R2 contains 0x00001111 6 | ADD R3, R1, R2 # R3 should be 0x00006666 7 | LLB R4, 0x6666 # R4 contains 0x00006666 8 | SUB R4, R3, R4 # compare R3 to known right answer 9 | B NEQ, L_FAIL # branch to fail routine 10 | 11 | ############################ 12 | ##Test BEQ basic function ## 13 | ############################ 14 | LLB R1, 0x5555 # R1 contains 0x00005555 15 | LLB R2, 0x1111 # R2 contains 0x00001111 16 | ADD R3, R1, R2 # R3 should be 0x00006666 17 | LLB R4, 0xA5A5 # R4 contains 0xFFFFA5A5 18 | SUB R4, R3, R4 # compare R3 to known right answer 19 | B EQ, L_FAIL # branch to fail routine 20 | 21 | ############################ 22 | ##Test BGT basic function ## 23 | ############################ 24 | LLB R1, 0x5555 # R1 contains 0x00005555 25 | LHB R1, 0x8000 # R1 contains 0x80005555 26 | LLB R2, 0x8000 # R2 contains 0xffff8000 27 | ADD R3, R1, R2 # R3 should be 0x80000000 28 | B GT, L_FAIL # branch to fail routine 29 | B GTE, L_FAIL # branch to fail routine 30 | 31 | ############################ 32 | ##Test BLT/E basic function ## 33 | ############################ 34 | LLB R1, 0x5555 # R1 contains 0x00005555 35 | LLB R2, 0x1111 # R2 contains 0x00001111 36 | ADD R3, R1, R2 # R3 should be 0x00006666 37 | ADD R3, R1, R2 # R3 should be 0x80000000 38 | B LT, L_FAIL # branch to fail routine 39 | B LTE, L_FAIL # branch to fail routine 40 | 41 | 42 | ############################ 43 | ##Test BOVFL basic function ## 44 | ############################ 45 | LLB R1, 0x5555 # R1 contains 0x00005555 46 | LHB R1, 0x5555 # R1 contains 0x55555555 47 | LLB R2, 0xfffe # R2 contains 0xfffffffe 48 | LHB R2, 0x7fff # R2 contains 0x7ffffffe 49 | ADD R3, R1, R2 # R3 should be 0x7fffffff 50 | B OVFL, L_PASS # branch to pass routine if overflow 51 | 52 | 53 | ######################### 54 | ##Pass routine at 0xAD ## 55 | ######################### 56 | ## Test BUNCOND basic function 57 | MEM 0x00AD 58 | L_PASS: 59 | B UNCOND, L_PASS 60 | 61 | ######################### 62 | ##Fail routine at 0xDD ## 63 | ######################### 64 | ## Test BUNCOND basic function 65 | MEM 0x00DD 66 | L_FAIL: 67 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/jump.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test JAL basic function ## 3 | ############################ 4 | JAL label 5 | 6 | JAL label2 7 | B UNCOND, L_FAIL 8 | 9 | label3: 10 | B UNCOND, L_PASS 11 | 12 | label2: 13 | JAL label3 14 | 15 | label: 16 | JR R31 17 | B UNCOND, L_FAIL 18 | 19 | 20 | ######################### 21 | ##Pass routine at 0xAD ## 22 | ######################### 23 | MEM 0x00AD 24 | L_PASS: 25 | B UNCOND, L_PASS 26 | 27 | ######################### 28 | ##Fail routine at 0xDD ## 29 | ######################### 30 | MEM 0x00DD 31 | L_FAIL: 32 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/llblhb.asm: -------------------------------------------------------------------------------- 1 | ################################ 2 | ##Test LLB/LHB basic function ## 3 | ################################ 4 | 5 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 6 | LHB R1, 0xF000 # R1 contains 0xF0000F0F 7 | LLB R2, 0x0004 # R2 contains 0x00000004 8 | SW R1, R2, 0 # DataMem[4] should contains 0xF0000F0F 9 | LW R3, R2, 0 # R3 should contains 0xF0000F0F 10 | LLB R4, 0x0F0F # R4 contains 0x0000000F 11 | LHB R4, 0xF000 # R4 contains 0xFFF0000F 12 | SUB R4, R3, R4 # compare R3 to known right answer 13 | B NEQ, L_FAIL # branch to fail routine 14 | 15 | ################################ 16 | ##Test LLB/LHB basic function ## 17 | ################################ 18 | 19 | LLB R1, 0xA5A5 # R1 contains 0xFFFFA5A5 20 | LHB R1, 0xA5A5 # R1 contains 0xA5A5A5A5 21 | LLB R2, 0x0008 # R2 contains 0x00000008 22 | SW R1, R2, 0 # DataMem[8] should contains 0xA5A5A5A5 23 | LW R3, R2, 0 # R3 should contains 0xF0000F0F 24 | LLB R4, 0xA5A5 # R4 contains 0xFFFFA5A5 25 | LHB R4, 0xA5A5 # R4 contains 0xA5A5A5A5 26 | SUB R4, R3, R4 # compare R3 to known right answer 27 | B NEQ, L_FAIL # branch to fail routine 28 | 29 | B UNCOND, L_PASS 30 | 31 | ######################### 32 | ##Pass routine at 0xAD ## 33 | ######################### 34 | MEM 0x00AD 35 | L_PASS: 36 | B UNCOND, L_PASS 37 | 38 | ######################### 39 | ##Fail routine at 0xDD ## 40 | ######################### 41 | MEM 0x00DD 42 | L_FAIL: 43 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/lwsw.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test LW/SW basic function ## 3 | ############################ 4 | 5 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 6 | LHB R1, 0xF000 # R1 contains 0xF0000F0F 7 | LLB R2, 0x0004 # R2 contains 0x00000004 8 | SW R1, R2, 0 # DataMem[4] should contains 0xF0000F0F 9 | LW R3, R2, 0 # R3 should contains 0xF0000F0F 10 | LLB R4, 0x0F0F # R4 contains 0x0000000F 11 | LHB R4, 0xF000 # R4 contains 0xFFF0000F 12 | SUB R4, R3, R4 # compare R3 to known right answer 13 | B NEQ, L_FAIL # branch to fail routine 14 | 15 | ############################ 16 | ##Test LW/SW basic function ## 17 | ############################ 18 | 19 | LLB R1, 0xA5A5 # R1 contains 0xFFFFA5A5 20 | LHB R1, 0xA5A5 # R1 contains 0xA5A5A5A5 21 | LLB R2, 0x0008 # R2 contains 0x00000008 22 | SW R1, R2, 0 # DataMem[8] should contains 0xA5A5A5A5 23 | LW R3, R2, 0 # R3 should contains 0xF0000F0F 24 | LLB R4, 0xA5A5 # R4 contains 0xFFFFA5A5 25 | LHB R4, 0xA5A5 # R4 contains 0xA5A5A5A5 26 | SUB R4, R3, R4 # compare R3 to known right answer 27 | B NEQ, L_FAIL # branch to fail routine 28 | 29 | B UNCOND, L_PASS 30 | 31 | ######################### 32 | ##Pass routine at 0xAD ## 33 | ######################### 34 | MEM 0x00AD 35 | L_PASS: 36 | B UNCOND, L_PASS 37 | 38 | ######################### 39 | ##Fail routine at 0xDD ## 40 | ######################### 41 | MEM 0x00DD 42 | L_FAIL: 43 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/mul.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test MUL basic function ## 3 | ############################ 4 | LLB R1, 0x0002 5 | LLB R2, 0x000F 6 | MUL R3, R1, R2 # 2 * 15 = 30 7 | LLB R4, 0x001E 8 | SUB R4, R4, R3 9 | B NEQ, L_FAIL 10 | 11 | ############################ 12 | ##Test MUL basic function ## 13 | ############################ 14 | LLB R1, 0xFFFE 15 | LHB R1, 0x0000 # intentionally put here 16 | # should only use lower 16-bit 17 | LLB R2, 0xFFF8 18 | LHB R2, 0x0000 # intentionally put here 19 | # should only use lower 16-bit 20 | MUL R3, R2, R1 # -2 * -8 = 16 21 | LLB R4, 0x0010 22 | SUB R4, R3, R4 23 | B NEQ, L_FAIL 24 | 25 | ############################ 26 | ##Test MUL basic function ## 27 | ############################ 28 | LLB R1, 0xFFFE 29 | LHB R1, 0x0000 # intentionally put here 30 | # should only use lower 16-bit 31 | LLB R2, 0x0008 32 | MUL R3, R2, R1 # -2 * 8 = -16 33 | LLB R4, 0xFFF0 34 | SUB R4, R3, R4 35 | B NEQ, L_FAIL 36 | 37 | ########################### 38 | ##Test MUL sets neg flag ## 39 | ########################### 40 | LLB R1, 0xFFFF 41 | LHB R1, 0x0000 # intentionally put here 42 | # should only use lower 16-bit 43 | LLB R2, 0x0008 44 | MUL R3, R2, R1 # -1 * 8 = -8 45 | B GTE, L_FAIL # branch to fail if negative flag is not set 46 | 47 | ################### 48 | ##Test edge case ## 49 | ################### 50 | LLB R1, 0x8000 51 | MUL R2, R1, R1 # -32768 * -32768 = 1073741824 52 | LLB R3, 0x0000 53 | LHB R3, 0x4000 54 | SUB R2, R2, R3 55 | B NEQ, L_FAIL 56 | 57 | ########################## 58 | ##Test MUL sets zr flag ## 59 | ########################## 60 | LLB R1, 0x0000 61 | LLB R2, 0xABCD 62 | MUL R2, R1, R2 63 | B NEQ, L_FAIL 64 | B UNCOND, L_PASS 65 | 66 | ######################### 67 | ##Pass routine at 0xAD ## 68 | ######################### 69 | MEM 0x00AD 70 | L_PASS: 71 | B UNCOND, L_PASS 72 | 73 | ######################### 74 | ##Fail routine at 0xDD ## 75 | ######################### 76 | MEM 0x00DD 77 | L_FAIL: 78 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/mulf.asm: -------------------------------------------------------------------------------- 1 | ################################### 2 | ##Test MULF does not set ov flag ## 3 | ################################### 4 | LLB R1, 0x0000 5 | LHB R1, 0x7F80 # positive infinite 6 | MULF R2, R1, R1 # results in pos_inf 7 | B OVFL, L_FAIL # branch to fail routine if overflow 8 | 9 | ############################ 10 | ##Test SUBF sets neg flag ## 11 | ############################ 12 | LLB R1, 0x0000 13 | LHB R1, 0xC000 14 | LLB R2, 0x0000 15 | LHB R2, 0x3F00 16 | MULF R2, R1, R2 # -2 * 0.5 = -1 17 | B GTE, L_FAIL # branch to fail if negative flag is not set 18 | 19 | ########################## 20 | ##Test MUL sets zr flag ## 21 | ########################## 22 | LLB R1, 0x0000 23 | LLB R2, 0x1234 24 | LHB R2, 0x5678 25 | MULF R2, R1, R2 # 0 * 68189266378752 = 0 26 | B NEQ, L_FAIL 27 | B UNCOND, L_PASS 28 | 29 | ############################################################## 30 | # A specific test to mimic average pooling from 4 fp numbers # 31 | ############################################################## 32 | LLB R2, 0x0000 33 | LHB R2, 0x3E80 # R2 <- 0.25F 34 | LLB R7, 0x0000 35 | LHB R7, 0x4120 # R7 <- 10.0F 36 | LLB R8, 0x0000 37 | LHB R8, 0x41A0 # R8 <- 20.0F 38 | LLB R9, 0x0000 39 | LHB R9, 0x4348 # R9 <- 200.0F 40 | LLB R10, 0x8000 41 | LHB R10, 0x4477 # R10 <- 990.0F 42 | 43 | ADDF R13, R0, R7 44 | ADDF R13, R13, R8 45 | ADDF R13, R13, R9 46 | ADDF R13, R13, R10 47 | MULF R13, R13, R2 # 1220 * 0.25 = 305 48 | LLB R20, 0x8000 49 | LHB R20, 0x4398 # R20 <- 305 50 | SUBF R20, R20, R13 51 | B NEQ, L_FAIL 52 | B UNCOND, L_PASS 53 | 54 | ######################### 55 | ##Pass routine at 0xAD ## 56 | ######################### 57 | MEM 0x00AD 58 | L_PASS: 59 | B UNCOND, L_PASS 60 | 61 | ######################### 62 | ##Fail routine at 0xDD ## 63 | ######################### 64 | MEM 0x00DD 65 | L_FAIL: 66 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/nor.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test NOR basic function ## 3 | ############################ 4 | LLB R1, 0x0000 # R1 contains 0x00000000 5 | LLB R2, 0x0F0F # R2 contains 0x00000F0F 6 | NOR R3, R1, R2 # R3 should be 0xFFFFF0F0 7 | LLB R4, 0xF0F0 # R4 contains 0xFFFFF0F0 8 | SUB R4, R3, R4 # compare R3 to known right answer 9 | B NEQ, L_FAIL # branch to fail routine 10 | 11 | ################################## 12 | ##Test that NOR sets carry flag ## 13 | ################################## 14 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 15 | LHB R1, 0x0F0F # R1 contains 0x0F0F0F0F 16 | LLB R2, 0xF0F0 # R2 contains 0x0000F0F0 17 | LHB R2, 0xF0F0 # R2 contains 0xF0F0F0F0 18 | NOR R3, R1, R2 # R3 should be 0x00000000 19 | B EQ, L_PASS # branch to pass routine if overflow 20 | B NEQ, L_FAIL # branch to fail routine 21 | 22 | ######################### 23 | ##Pass routine at 0xAD ## 24 | ######################### 25 | MEM 0x00AD 26 | L_PASS: 27 | B UNCOND, L_PASS 28 | 29 | ######################### 30 | ##Fail routine at 0xDD ## 31 | ######################### 32 | MEM 0x00DD 33 | L_FAIL: 34 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/poppush.asm: -------------------------------------------------------------------------------- 1 | ################################# 2 | ##Test POP/PUSH basic function ## 3 | ################################# 4 | LLB R1, 0x5678 5 | LHB R1, 0x1234 # R1 contains 0x12345678 6 | LLB R2, 0x5678 7 | LHB R2, 0x1234 # R2 contains 0x12345678 8 | PUSH R1 9 | ADDI R1, R1, 0x78 10 | SUBI R1, R1, 0xCD # alter R1 content 11 | POP R1 12 | SUB R3, R1, R2 # R3 should be 0 13 | B NEQ, L_FAIL 14 | 15 | ############################################## 16 | ## A specific test for a bug we encountered ## 17 | ## This code mimics a 2 * 2 average polling ## 18 | ############################################## 19 | LLB R3, 8 # R3 contains 8 20 | LLB R4, 8 # R4 contains 8 21 | LW R7, R3, 0 # R7 <- DMem[8] 22 | LW R8, R3, 1 # R8 <- DMem[9] 23 | PUSH R3 # push R3 to stack 24 | ADD R3, R3, R4 # R3 contians 16 25 | LW R9, R3, 0 # R9 <- DMem[16] 26 | LW R10, R3, 1 # R10 <- DMem[17] 27 | POP R3 # restore R3 28 | ADDI R3, R3, 2 # R3 should be 10 here 29 | # but it was 2 30 | # see bypass signals fixes in id stage 31 | 32 | ################################# 33 | ##Multiple POP/PUSH operations ## 34 | ################################# 35 | LLB R2, 0x0222 36 | LLB R3, 0x0333 37 | LLB R4, 0x0444 38 | LLB R5, 0x0555 39 | LLB R6, 0x0666 40 | LLB R7, 0x0777 41 | LLB R8, 0x0888 42 | LLB R9, 0x0999 43 | # callee-saves 44 | PUSH R2 45 | PUSH R3 46 | PUSH R4 47 | PUSH R5 48 | PUSH R6 49 | PUSH R7 50 | PUSH R8 51 | PUSH R9 52 | ADD R2, R0, R0 53 | ADD R3, R0, R0 54 | ADD R4, R0, R0 55 | ADD R5, R0, R0 56 | ADD R6, R0, R0 57 | ADD R7, R0, R0 58 | ADD R8, R0, R0 59 | ADD R9, R0, R0 60 | # callee-restores 61 | POP R9 62 | POP R8 63 | POP R7 64 | POP R6 65 | POP R5 66 | POP R4 67 | POP R3 68 | POP R2 69 | LLB R12, 0x0222 70 | LLB R13, 0x0333 71 | LLB R14, 0x0444 72 | LLB R15, 0x0555 73 | LLB R16, 0x0666 74 | LLB R17, 0x0777 75 | LLB R18, 0x0888 76 | LLB R19, 0x0999 77 | SUB R2, R2, R12 78 | B NEQ, L_FAIL 79 | SUB R3, R3, R13 80 | B NEQ, L_FAIL 81 | SUB R4, R4, R14 82 | B NEQ, L_FAIL 83 | SUB R5, R5, R15 84 | B NEQ, L_FAIL 85 | SUB R6, R6, R16 86 | B NEQ, L_FAIL 87 | SUB R7, R7, R17 88 | B NEQ, L_FAIL 89 | SUB R8, R8, R18 90 | B NEQ, L_FAIL 91 | SUB R9, R9, R19 92 | B NEQ, L_FAIL 93 | B UNCOND, L_PASS 94 | 95 | ######################### 96 | ##Pass routine at 0xAD ## 97 | ######################### 98 | MEM 0x00AD 99 | L_PASS: 100 | B UNCOND, L_PASS 101 | 102 | ######################### 103 | ##Fail routine at 0xDD ## 104 | ######################### 105 | MEM 0x00DD 106 | L_FAIL: 107 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/sll.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test SLL basic function ## 3 | ############################ 4 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 5 | SLL R3, R1, 0x10 # R3 should be 0x0F0F0000 6 | LLB R4, 0x0000 # R4 contains 0x00000000 7 | LHB R4, 0x0F0F # R4 contains 0x0F0F0000 8 | SUB R4, R3, R4 # compare R3 to known right answer 9 | B NEQ, L_FAIL # branch to fail routine 10 | 11 | ############################ 12 | ##Test SLL basic function ## 13 | ############################ 14 | LLB R1, 0x0000 # R1 contains 0x00000000 15 | LHB R1, 0x0F0F # R1 contains 0x0F0F0000 16 | SLL R3, R1, 0x08 # R3 should be 0x0F000000 17 | LLB R4, 0x0000 # R4 contains 0x00000000 18 | LHB R4, 0x0F00 # R4 contains 0x0F000000 19 | SUB R4, R3, R4 # compare R3 to known right answer 20 | B NEQ, L_FAIL # branch to fail routine 21 | 22 | ################################## 23 | ##Test that SLL sets carry flag ## 24 | ################################## 25 | LLB R1, 0x0000 # R1 contains 0x00000F0F 26 | LHB R1, 0x0000 # R1 contains 0x0F0F0F0F 27 | SLL R3, R1, 0x04 # R3 should be 0x00000000 28 | B EQ, L_PASS # branch to pass routine if overflow 29 | B NEQ, L_FAIL # branch to fail routine 30 | 31 | ######################### 32 | ##Pass routine at 0xAD ## 33 | ######################### 34 | MEM 0x00AD 35 | L_PASS: 36 | B UNCOND, L_PASS 37 | 38 | ######################### 39 | ##Fail routine at 0xDD ## 40 | ######################### 41 | MEM 0x00DD 42 | L_FAIL: 43 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/sra.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test SRA basic function ## 3 | ############################ 4 | 5 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 6 | LHB R1, 0xF000 # R1 contains 0xF0000F0F 7 | SRA R3, R1, 0x08 # R3 should be 0xFFF0000F 8 | LLB R4, 0x000F # R4 contains 0x0000000F 9 | LHB R4, 0xFFF0 # R4 contains 0xFFF0000F 10 | SUB R4, R3, R4 # compare R3 to known right answer 11 | B NEQ, L_FAIL # branch to fail routine 12 | 13 | ############################ 14 | ##Test SRA basic function ## 15 | ############################ 16 | 17 | LLB R1, 0x0000 # R1 contains 0x00000000 18 | LHB R1, 0x0F0F # R1 contains 0x0F0F0000 19 | SRA R3, R1, 0x10 # R3 should be 0x00000F0F 20 | LLB R4, 0x0F0F # R4 contains 0x00000000 21 | LHB R4, 0x0000 # R4 contains 0x0F0F0000 22 | SUB R4, R3, R4 # compare R3 to known right answer 23 | B NEQ, L_FAIL # branch to fail routine 24 | 25 | ################################## 26 | ##Test that SRA sets carry flag ## 27 | ################################## 28 | ## should set overflow 29 | LLB R1, 0x0000 # R1 contains 0x00000F0F 30 | LHB R1, 0x0000 # R1 contains 0x0F0F0F0F 31 | SRA R3, R1, 0x04 # R3 should be 0x00000000 32 | B EQ, L_PASS # branch to pass routine if overflow 33 | B NEQ, L_FAIL # branch to fail routine 34 | 35 | ######################### 36 | ##Pass routine at 0xAD ## 37 | ######################### 38 | MEM 0x00AD 39 | L_PASS: 40 | B UNCOND, L_PASS 41 | 42 | ######################### 43 | ##Fail routine at 0xDD ## 44 | ######################### 45 | MEM 0x00DD 46 | L_FAIL: 47 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/srl.asm: -------------------------------------------------------------------------------- 1 | ############################ 2 | ##Test SRL basic function ## 3 | ############################ 4 | 5 | LLB R1, 0x0F0F # R1 contains 0x00000F0F 6 | SRL R3, R1, 0x08 # R3 should be 0x0000000F 7 | LLB R4, 0x000F # R4 contains 0x0000000F 8 | LHB R4, 0x0000 # R4 contains 0x0000000F 9 | SUB R4, R3, R4 # compare R3 to known right answer 10 | B NEQ, L_FAIL # branch to fail routine 11 | 12 | ############################ 13 | ##Test SRL basic function ## 14 | ############################ 15 | 16 | LLB R1, 0x0000 # R1 contains 0x00000000 17 | LHB R1, 0x0F0F # R1 contains 0x0F0F0000 18 | SRL R3, R1, 0x10 # R3 should be 0x00000F0F 19 | LLB R4, 0x0F0F # R4 contains 0x00000000 20 | LHB R4, 0x0000 # R4 contains 0x0F0F0000 21 | SUB R4, R3, R4 # compare R3 to known right answer 22 | B NEQ, L_FAIL # branch to fail routine 23 | 24 | ################################## 25 | ##Test that SRL sets carry flag ## 26 | ################################## 27 | ## should set overflow 28 | LLB R1, 0x0000 # R1 contains 0x00000F0F 29 | LHB R1, 0x0000 # R1 contains 0x0F0F0F0F 30 | SRL R3, R1, 0x04 # R3 should be 0x00000000 31 | B EQ, L_PASS # branch to pass routine if overflow 32 | B NEQ, L_FAIL # branch to fail routine 33 | 34 | ######################### 35 | ##Pass routine at 0xAD ## 36 | ######################### 37 | MEM 0x00AD 38 | L_PASS: 39 | B UNCOND, L_PASS 40 | 41 | ######################### 42 | ##Fail routine at 0xDD ## 43 | ######################### 44 | MEM 0x00DD 45 | L_FAIL: 46 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/subf.asm: -------------------------------------------------------------------------------- 1 | ################################### 2 | ##Test SUBF does not set ov flag ## 3 | ################################### 4 | LLB R1, 0x0000 5 | LHB R1, 0x7F80 # positive infinite 6 | LLB R3, 0x0000 7 | SUBF R2, R3, R1 # results in neg_inf 8 | B OVFL, L_FAIL # branch to fail routine if overflow 9 | 10 | ############################ 11 | ##Test SUBF sets neg flag ## 12 | ############################ 13 | LLB R1, 0x0000 14 | LHB R1, 0xC000 15 | LLB R2, 0x0000 16 | LHB R2, 0x3FA0 17 | SUBF R2, R1, R2 # -2 - 1.25 = -3.25 18 | B GTE, L_FAIL # branch to fail if negative flag is not set 19 | 20 | ########################## 21 | ##Test MUL sets zr flag ## 22 | ########################## 23 | LLB R1, 0x0000 24 | LLB R2, 0x0000 25 | LHB R2, 0x8000 26 | SUBF R2, R1, R2 # 0 - (-0) = -0 27 | B NEQ, L_FAIL 28 | B UNCOND, L_PASS 29 | 30 | ######################### 31 | ##Pass routine at 0xAD ## 32 | ######################### 33 | MEM 0x00AD 34 | L_PASS: 35 | B UNCOND, L_PASS 36 | 37 | ######################### 38 | ##Fail routine at 0xDD ## 39 | ######################### 40 | MEM 0x00DD 41 | L_FAIL: 42 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/test2.asm: -------------------------------------------------------------------------------- 1 | B UNCOND, L_PASS 2 | 3 | ######################### 4 | ##Fail routine at 0xAD ## 5 | ######################### 6 | MEM 0x00AD 7 | L_PASS:B UNCOND, L_PASS 8 | 9 | ######################### 10 | ##Fail routine at 0xDD ## 11 | ######################### 12 | MEM 0x00DD 13 | L_FAIL: B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/test/umul.asm: -------------------------------------------------------------------------------- 1 | ############################# 2 | ##Test UMUL basic function ## 3 | ############################# 4 | LLB R1, 0x0002 5 | LLB R2, 0x000F 6 | UMUL R3, R1, R2 # 2 * 15 = 30 7 | LLB R4, 0x001E 8 | SUB R4, R4, R3 9 | B NEQ, L_FAIL 10 | 11 | ############################# 12 | ##Test UMUL basic function ## 13 | ############################# 14 | LLB R1, 0xFFFE 15 | LLB R2, 0x0008 16 | UMUL R3, R2, R1 # 65534 * 8 = 524272 17 | LLB R4, 0xFFF0 18 | LHB R4, 0x0007 19 | SUB R4, R3, R4 20 | B NEQ, L_FAIL 21 | 22 | ################################## 23 | ##Test UMUL never sets neg flag ## 24 | ################################## 25 | LLB R1, 0xFFFF 26 | UMUL R2, R1, R1 # 65535 * 65535 = 4294836225 27 | # R2 contains FFFE0001 28 | B LT, L_FAIL # branch to fail routine if negative flag is set 29 | 30 | ########################### 31 | ##Test UMUL sets zr flag ## 32 | ########################### 33 | LLB R1, 0x0000 34 | LLB R2, 0xABCD 35 | UMUL R2, R1, R2 36 | B NEQ, L_FAIL 37 | B UNCOND, L_PASS 38 | 39 | ######################### 40 | ##Pass routine at 0xAD ## 41 | ######################### 42 | MEM 0x00AD 43 | L_PASS: 44 | B UNCOND, L_PASS 45 | 46 | ######################### 47 | ##Fail routine at 0xDD ## 48 | ######################### 49 | MEM 0x00DD 50 | L_FAIL: 51 | B UNCOND, L_FAIL -------------------------------------------------------------------------------- /Project/SourceCode/weight_cnn_rom.sv: -------------------------------------------------------------------------------- 1 | module weight_cnn_rom(clk,raddr,rdata); 2 | 3 | input clk; 4 | //input [12:0] raddr; 5 | input [15:0] raddr; 6 | output reg [31:0] rdata; 7 | 8 | reg [31:0]rom[0:63653]; // CNN kernels and weights 9 | 10 | initial 11 | $readmemh("../weightcnn.hex",rom); 12 | 13 | always @(negedge clk) begin 14 | rdata <= rom[raddr]; 15 | end 16 | 17 | endmodule 18 | -------------------------------------------------------------------------------- /Project/SourceCode/weight_nn_rom.sv: -------------------------------------------------------------------------------- 1 | module weight_nn_rom(clk,raddr,rdata); 2 | 3 | input clk; 4 | //input [12:0] raddr; 5 | input [15:0] raddr; 6 | output reg [31:0] rdata; 7 | 8 | reg [31:0]rom[0:50815]; //The current weight mem is 32 bit floating point x (28x28) x 10 9 | 10 | initial 11 | $readmemh("../weightnn.hex",rom); 12 | 13 | always @(negedge clk) begin 14 | rdata <= rom[raddr]; 15 | end 16 | 17 | endmodule 18 | -------------------------------------------------------------------------------- /Project/SourceCode/weight_rom.sv: -------------------------------------------------------------------------------- 1 | module weight_rom(clk,raddr,rdata); 2 | 3 | input clk; 4 | input [12:0] raddr; 5 | output reg [31:0] rdata; 6 | 7 | reg [31:0]rom[0:7839]; //The current weight mem is 32 bit floating point x (28x28) x 10 8 | 9 | initial 10 | $readmemh("../weight.hex",rom); 11 | 12 | always @(negedge clk) begin 13 | rdata <= rom[raddr]; 14 | end 15 | 16 | endmodule 17 | -------------------------------------------------------------------------------- /Project/Specifications/ECE554_Final_Report.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/ECE554_Final_Report.docx -------------------------------------------------------------------------------- /Project/Specifications/ECE554_Interface_Document.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/ECE554_Interface_Document.docx -------------------------------------------------------------------------------- /Project/Specifications/ISA.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/ISA.xlsx -------------------------------------------------------------------------------- /Project/Specifications/ProjectOverview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/ProjectOverview.pdf -------------------------------------------------------------------------------- /Project/Specifications/ProjectProposalDoc554.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/ProjectProposalDoc554.docx -------------------------------------------------------------------------------- /Project/Specifications/WISC-S14 ISA.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/WISC-S14 ISA.pdf -------------------------------------------------------------------------------- /Project/Specifications/block diagram.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/Project/Specifications/block diagram.pptx -------------------------------------------------------------------------------- /Project/asm_tests/ADDF.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0xc280 2 | LHB R1, 0x3fd7 # 1.6856231689453125 3 | LLB R2, 0xc780 4 | LHB R2, 0x3f14 # 0.58116912841796875 5 | ADDF R3, R1, R2 6 | 7 | # The result should be 0x40111320 2.266792297 -------------------------------------------------------------------------------- /Project/asm_tests/ADDI.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 78 2 | ADDI R3, R1, 34 3 | 4 | # The result should be 112 -------------------------------------------------------------------------------- /Project/asm_tests/FTI.asm: -------------------------------------------------------------------------------- 1 | LLB R30, 0x4d20 2 | LHB R30, 0x4705 # 34125.125 3 | FTI R31, R30 4 | 5 | # The result should be 0x854D 34125 -------------------------------------------------------------------------------- /Project/asm_tests/ITF.asm: -------------------------------------------------------------------------------- 1 | LLB R2, 1234 2 | ITF R3, R2 3 | 4 | # The result should be 0x449a4000 1234 -------------------------------------------------------------------------------- /Project/asm_tests/MUL.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0xABCD #-21555 2 | LLB R2, 0x78EF #30959 3 | MUL R3, R1, R2 4 | 5 | # The result should be 0xD8397C63 -667321245 -------------------------------------------------------------------------------- /Project/asm_tests/MULF.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0xc280 2 | LHB R1, 0x3fd7 # 1.6856231689453125 3 | LLB R2, 0xc780 4 | LHB R2, 0x3f14 # 0.58116912841796875 5 | MULF R3, R2, R1 6 | 7 | # The result should be 0x3f7ac92c 0.9796321479 -------------------------------------------------------------------------------- /Project/asm_tests/PUSH_POP.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0x1234 2 | LLB R2, 0xABCD 3 | PUSH R1 4 | PUSH R2 5 | 6 | POP R3 # should receive 0xABCD 7 | POP R4 # should receive 0x1234 -------------------------------------------------------------------------------- /Project/asm_tests/SUBF.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0xc280 2 | LHB R1, 0x3fd7 # 1.6856231689453125 3 | LLB R2, 0xc780 4 | LHB R2, 0x3f14 # 0.58116912841796875 5 | SUBF R3, R2, R1 6 | 7 | # The result should be 0xbf8d5ec0 -1.104454041 -------------------------------------------------------------------------------- /Project/asm_tests/SUBI.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 78 2 | SUBI R3, R1, 34 3 | 4 | # The result should be 44 -------------------------------------------------------------------------------- /Project/asm_tests/UMUL.asm: -------------------------------------------------------------------------------- 1 | LLB R1, 0xABCD #-21555 2 | LLB R2, 0x78EF #30959 3 | UMUL R3, R1, R2 4 | 5 | # The result should be 0x51287c63 1,361,607,779 -------------------------------------------------------------------------------- /Project/asm_tests/translate_test.asm: -------------------------------------------------------------------------------- 1 | # The purpose of this asm to test the translation for every single command 2 | ADD R31, R0, R15 3 | ADDZ R1, R2, R3 4 | SUB R31, R30, R29 5 | AND R4, R5, R6 6 | NOR R7, R7, R7 7 | 8 | SLL R1, R31, 19 9 | SRL R30, R2, 0x1F 10 | SRA R1, R2, 15 11 | 12 | LW R16, R16, 0xFF 13 | SW R17, R19, 0 14 | 15 | LHB R9, 0xDEAD 16 | LLB R9, 0xBEEF 17 | 18 | B neq, TEST 19 | B eq, TEST 20 | B GT, TEST 21 | B LT, TEST 22 | B GTE, TEST 23 | B LTE, TEST 24 | B OVFL, TEST 25 | B UNCOND, TEST 26 | 27 | JAL test 28 | 29 | 30 | 31 | 32 | TEST: 33 | 34 | JR R5 35 | 36 | LWI R1, R2, 255 37 | 38 | PUSH R2 39 | POP R3 40 | 41 | MUL R1, R2, R31 42 | UMUL R7, R8, R9 43 | ADDF R10, R11, R12 44 | SUBF R13, R14, R15 45 | MULF R16, R17, R18 46 | ITF R19, R20 47 | FTI R21, R22 48 | 49 | HLT 50 | 51 | -------------------------------------------------------------------------------- /Project/other_extended_modules/extended_ALU.sv: -------------------------------------------------------------------------------- 1 | module extended_ALU(clk, src1, src0, func, dst_EX_DM, ov, zr, neg); 2 | // Encoding of func[2:0] is as follows: // 3 | // 000 ==> MUL 4 | // 001 ==> UMUL 5 | // 010 ==> ADDF 6 | // 011 ==> SUBF 7 | // 100 ==> MULF 8 | // 101 ==> ITF 9 | // 110 ==> FTI 10 | // 111 ==> undefined 11 | 12 | `include "common_params.inc" 13 | 14 | input clk; 15 | input [31:0] src1, src0; 16 | input [2:0] func; // selects function to perform 17 | output reg [31:0] dst_EX_DM; 18 | output ov, zr, neg; 19 | 20 | logic [31:0] ifadd_OUT, ifmul_OUT, iftoi_OUT, iitof_OUT, iimul_OUT; 21 | 22 | logic [31:0] OUT; 23 | 24 | /////////////////////// 25 | // compute modules // 26 | ///////////////////// 27 | 28 | FP_adder ifadd( 29 | .A(src1), 30 | .B(func==SUBF ? {~src0[31], src0[30:0]} : src0), // flip second operand if doing A - B 31 | .out(ifadd_OUT) 32 | ); 33 | 34 | FP_mul ifmul( 35 | .A(src1), 36 | .B(src0), 37 | .OUT(ifmul_OUT) 38 | ); 39 | 40 | float_to_signed_int iftoi( 41 | .FP_val(src1), 42 | .signed_int_val(iftoi_OUT) 43 | ); 44 | 45 | signed_int_to_float iitof( 46 | .signed_int_val(src1), 47 | .FP_val(iitof_OUT) 48 | ); 49 | 50 | int_mul_16by16 iimul( 51 | .A(src1), 52 | .B(src0), 53 | .sign(~func[0]), // 0 ==> MUL 1 ==> UMUL 54 | .OUT(iimul_OUT) 55 | ); 56 | 57 | /////////////////////////////////// 58 | // Multiplexing function of ALU // 59 | ///////////////////////////////// 60 | assign OUT = (func==MUL || func==UMUL) ? iimul_OUT : 61 | (func==ADDF || func==SUBF) ? ifadd_OUT : 62 | (func==MULF) ? ifmul_OUT : 63 | (func==ITF) ? iitof_OUT : 64 | (func==FTI) ? iftoi_OUT : 65 | 32'hDEADDEAD; // undefined behavior 66 | 67 | ///////////////////////// 68 | // Set flag variables // 69 | /////////////////////// 70 | // these 7 instructions can NEVER overflow (FP operations are saturating following their own rules) 71 | assign ov = 1'b0; 72 | 73 | // assign zero flag according to if output is in normal format or FP format 74 | assign zr = (func==MUL || func==UMUL || func==FTI) ? |OUT : |OUT[30:0]; 75 | 76 | // assign neg flag according to if output is signed or unsigned 77 | assign neg = (func==UMUL) ? 1'b0 : OUT[31]; 78 | 79 | ////////////////////////// 80 | // Flop the ALU result // 81 | //////////////////////// 82 | always @(posedge clk) 83 | dst_EX_DM <= OUT; 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /Project/other_extended_modules/int_mul_16by16.sv: -------------------------------------------------------------------------------- 1 | module int_mul_16by16(A, B, sign, OUT); 2 | 3 | input [15:0] A; // 16 bit integer input 4 | input [15:0] B; // 16 bit integer input 5 | input sign; // signed multiply when set, unsigned multiply when unsigned 6 | output [31:0] OUT; // the product of A*B 7 | 8 | logic signed [16:0] A_eff, B_eff; 9 | logic signed [33:0] product; 10 | 11 | assign A_eff = {sign ? A[15] : 1'b0, A}; 12 | assign B_eff = {sign ? B[15] : 1'b0, B}; 13 | 14 | assign product = A_eff * B_eff; 15 | 16 | assign OUT = product[31:0]; 17 | 18 | endmodule -------------------------------------------------------------------------------- /Project/other_extended_modules/int_mul_16by16_tb.sv: -------------------------------------------------------------------------------- 1 | module int_mul_16by16_tb(); 2 | 3 | logic [15:0] A; // 16 bit integer input 4 | logic [15:0] B; // 16 bit integer input 5 | logic sign; // signed multiply when set, unsigned multiply when unsigned 6 | logic [31:0] OUT; // the product of A*B 7 | 8 | int temp; 9 | 10 | int_mul_16by16 iDUT( 11 | .A(A), 12 | .B(B), 13 | .sign(sign), 14 | .OUT(OUT) 15 | ); 16 | 17 | initial begin 18 | // test unsigned multiplication 19 | sign = 0; 20 | for(int i = 0; i < 100; i++) begin 21 | temp = $random(); 22 | A = temp[31:16]; 23 | B = temp[15:0]; 24 | #1; 25 | if(OUT !== A * B) begin 26 | $display("wrong answer!"); 27 | $stop(); 28 | end 29 | end 30 | 31 | // test signed multiplication 32 | sign = 1; 33 | for(int i = 0; i < 100; i++) begin 34 | temp = $random(); 35 | A = temp[31:16]; 36 | B = temp[15:0]; 37 | #1; 38 | if(signed'(OUT) !== signed'(A) * signed'(B)) begin 39 | $display("wrong answer!"); 40 | $stop(); 41 | end 42 | end 43 | 44 | $display("ALL TESTS PASSED!!!"); 45 | $stop(); 46 | end 47 | 48 | endmodule -------------------------------------------------------------------------------- /Project/other_extended_modules/stack.sv: -------------------------------------------------------------------------------- 1 | // This is a 32x1024 stack for PUSH and POP instructions 2 | // Only one operation can be performed at a time 3 | module stack(clk, rst_n, push, pop, wdata,rdata); 4 | input clk; // system clock 5 | input rst_n; // active low async reset 6 | input push; // write into stack 7 | input pop; // pop from stack 8 | input [31:0] wdata; // data to write 9 | output [31:0] rdata; // read data output 10 | 11 | reg [31:0] mem [1023:0]; // 32 by 1024 SRAM block 12 | 13 | reg [10:0] addr; // 10 bit address for stack pointer, 1 extra bit for 1024th data 14 | wire full, empty; // signals to control the edge behavior 15 | 16 | assign rdata = mem[addr]; 17 | assign full = addr == 11'h400; 18 | assign empty = addr == 10'h000; 19 | 20 | // negedge triggered memory 21 | always @(negedge clk) begin 22 | if(push & ~full) 23 | mem[addr] <= wdata; 24 | end 25 | 26 | always @(negedge clk, negedge rst_n) begin 27 | if (!rst_n) 28 | addr <= 11'h000; 29 | else if (push & ~full) 30 | addr <= addr + 11'h001; 31 | else if (pop & ~empty) 32 | addr <= addr - 11'h001; 33 | end 34 | 35 | endmodule -------------------------------------------------------------------------------- /Project/simulation/image_mem.sv: -------------------------------------------------------------------------------- 1 | module image_mem(clk,we,waddr,wdata,raddr,rdata); 2 | 3 | input clk; 4 | input we; 5 | input [9:0] waddr; 6 | input [7:0] wdata; 7 | input [9:0] raddr; 8 | output reg [7:0] rdata; 9 | 10 | reg [7:0]mem[0:1023]; 11 | 12 | initial 13 | $readmemh("../fixed_image_cnn.hex",mem); 14 | 15 | always @(negedge clk) begin 16 | if (we) 17 | mem[waddr] <= wdata; 18 | rdata <= mem[raddr]; 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /Project/simulation/top_tb.v: -------------------------------------------------------------------------------- 1 | module top_tb(); 2 | 3 | reg clk, rst_n; 4 | 5 | ImageRecog iDUT( 6 | .ref_clk(clk), 7 | .RST_n(rst_n) 8 | ); 9 | 10 | initial begin 11 | clk = 0; 12 | rst_n = 0; 13 | #2 rst_n = 1; 14 | end 15 | 16 | always 17 | #1 clk = ~clk; 18 | 19 | endmodule -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPGA Implementation of CNN Handwritten Character Recognition 2 | ## ECE554_SP23 Senior Capstone Design at UW-Madison 3 | **Owned by Team Poor Handwriting:
** 4 |   Supervisor (Instructor): Eric Hoffman
5 |   Team Lead: Shichen (Justin) Qiao
6 |   Hardware Architect: Lingkai (Harry) Zhao
7 |   RTL Design Engineer: Haining Qiu
8 |   Machine Learning Engineer: Qikun Liu
9 |
10 | **Project Demo:
** 11 | https://youtu.be/7T7qIo2IxYQ 12 | 13 | **Hardware Requirements:
** 14 |   -Altera DE1 Development and Education Board: https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=83
15 |   -TerasIC TRDB-D5M Camera: https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=68&No=281
16 |   -USB to 6-Wire UART Cable
17 |   -VGA Cable and Monitor (640 by 480)
18 | 19 | **Summary
** 20 | Machine Learning (ML) has been a skyrocketing field in Computer Science in recent years. As computer hardware engineers, we are enthusiastic about hardware implementations of popular software ML architectures to optimize their performance, reliability, and resource usage.

21 | Our project involved designing a real-time device for recognizing handwritten letters and digits using an Altera DE1 FPGA Kit. We implemented and validated three different ML architectures: linear classification, a 784-64-10 fully connected neural network (NN), and a LeNet-5 CNN with ReLU activation layers and 36 classes. The training processes were done in Python scripts, and the resulting kernels and weights were stored in hex files and loaded into the FPGA's SRAM units. We wrote assembly code for our custom 32-bit floating-point instruction set architecture (ISA) to perform classification and developed a 5-stage MIPS processor in SystemVerilog to manage image processing, matrix multiplications, and user interfaces. We followed various engineering standards, including IEEE-754 32-bit Floating Point Standard, Video Graphics Array (VGA) display protocol, Universal Asynchronous Receiver-Transmitter (UART) protocol, and Inter-Integrated Circuit (I2C) protocols to achieve our project goals.

22 | This report (https://github.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/blob/main/ECE554_Final_Report.pdf) documents the high-level design block diagrams, interfaces between each System Verilog module, implementation details of our software and firmware components, and the potential impacts of our project on society. Additionally, we will provide a final demonstration and discuss each team member's contributions to this senior capstone project.

23 | -------------------------------------------------------------------------------- /demo_pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShichenQiao/ECE554_SP23_FPGA_Handwriting_Recognition/e1e6b7387124f2fa50165da59b8bb217b94d004f/demo_pic.jpg --------------------------------------------------------------------------------