├── 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@