diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | hdl/mips_system.v | 31 | ||||
-rw-r--r-- | hdl/rot_ctrl.v | 126 | ||||
-rw-r--r-- | hdl/testbench.v | 7 | ||||
-rw-r--r-- | hdl/wb_rot_ctrl.v | 69 | ||||
-rw-r--r-- | hdl/wb_rot_ctrl_testbench.v | 82 | ||||
-rw-r--r-- | hdl/wb_slave_ctrl.v | 76 | ||||
-rw-r--r-- | hdl/wb_slave_ctrl_testbench.v | 90 | ||||
-rw-r--r-- | sw/test.asm | 18 |
9 files changed, 486 insertions, 19 deletions
@@ -0,0 +1,6 @@ +Форк https://github.com/sbikovsky/MIPSLabs.git +------------------------------------------------- + +Лабораторная работа #1 по курсу `Схемотехника ЭВМ` + + diff --git a/hdl/mips_system.v b/hdl/mips_system.v index d9959b3..7a273dd 100644 --- a/hdl/mips_system.v +++ b/hdl/mips_system.v @@ -5,7 +5,8 @@ module mips_system ( input wire clk, input wire rst, - + input wire rot_a_i, + input wire rot_b_i, output [7:0] led ); localparam [31:0] instr_addr_high = 32'h000001ff, @@ -54,8 +55,8 @@ module mips_system ( wire ram_stb_i; wire ram_ack_o; wire [2:0] ram_cti_i = 0; // classic cycle - - gpio_wb #(gpio_base_addr) gpio_inst( + + wb_rot_ctrl #(gpio_base_addr) wb_rot_ctrl( // system signals .clk_i(clk), @@ -70,10 +71,32 @@ module mips_system ( .cyc_i(gpio_cyc_i), .stb_i(gpio_stb_i), .ack_o(gpio_ack_o), + .rot_a_i(rot_a_i), + .rot_b_i(rot_b_i), // func signals - .gpio_o(led) + .led_o(led) ); + + /*gpio_wb #(gpio_base_addr) gpio_inst( + + // system signals + .clk_i(clk), + .rst_i(rst), + + // wb signals + .dat_i(gpio_dat_i), + .dat_o(gpio_dat_o), + .adr_i(gpio_adr_i), + .we_i(gpio_we_i), + .sel_i(gpio_sel_i), + .cyc_i(gpio_cyc_i), + .stb_i(gpio_stb_i), + .ack_o(gpio_ack_o), + + // func signals + .gpio_o(led) + );*/ data_ram_wb #( .addr_high(data_addr_high), diff --git a/hdl/rot_ctrl.v b/hdl/rot_ctrl.v new file mode 100644 index 0000000..5bd8fc1 --- /dev/null +++ b/hdl/rot_ctrl.v @@ -0,0 +1,126 @@ +`timescale 1ns / 1ps + +module debouncer( reset, clk, noisy, clean ); + input reset, clk, noisy; + output clean; + + parameter NDELAY = 1000; + parameter NBITS = 20; + + reg [NBITS-1:0] count; + reg xnew, clean; + + always @(posedge clk) + if (reset) begin + xnew <= noisy; + clean <= noisy; + count <= 0; + end + else if(noisy != xnew) + begin + xnew <= noisy; + count <= 0; + end + else if(count == NDELAY) + clean <= xnew; + else + count <= count + 1; +endmodule + +module diff( input clk_i, input rst_i, input sig_i, output reg val_o, output reg oneclk_o ); + reg last_value; + + always @(posedge clk_i) + if( rst_i ) + begin + oneclk_o <= 0; + last_value <= 0; + val_o <= 0; + end + else if( last_value != sig_i ) + begin + last_value <= sig_i; + + oneclk_o <= sig_i; + val_o <= 1; + end + else + begin + oneclk_o <= 0; + val_o <= 0; + end + +endmodule + +module rot_ctrl( + input clk_i, + input rst_i, + input rot_a_i, + input rot_b_i, + + input[7:0] data_i, + input data_val_i, + + input[7:0] step_i, + input step_val_i, + + output[7:0] led_o, + + output [7:0] data_o, + output [7:0] step_o + ); + + reg[7:0] data; + reg[7:0] step; + + reg stateA; + reg stateB; + + assign led_o = data; + assign step_o = step; + assign data_o = data; + + wire rot_a_clean; + wire rot_b_clean; + + debouncer debounceA(rst_i, clk_i, rot_a_i, rot_a_clean); + debouncer debounceB(rst_i, clk_i, rot_b_i, rot_b_clean); + + wire rot_a_diff; + wire rot_b_diff; + wire rot_a_diff_val; + wire rot_b_diff_val; + diff diffA(clk_i, rst_i, rot_a_clean, rot_a_diff_val, rot_a_diff); + diff diffB(clk_i, rst_i, rot_b_clean, rot_b_diff_val, rot_b_diff); + + always @(posedge clk_i) + begin + if (rot_a_diff_val) + stateA <= rot_a_diff; + else if (rot_b_diff_val) + stateB <= rot_b_diff; + end + + always @(posedge clk_i) + if( rst_i ) + step <= 1; + else if( step_val_i ) + step <= step_i; + + always @(posedge clk_i) + begin + if( rst_i ) + data <= 0; + else if( data_val_i ) + data <= data_i; + else if( rot_a_diff == 1 && stateB == 0 ) + data <= data + step; + if( rot_b_diff == 1 && stateA == 0 ) + begin + if( data < step ) + data <= 0; + else + data <= data - step; + end + end +endmodule
\ No newline at end of file diff --git a/hdl/testbench.v b/hdl/testbench.v index fc9d23e..bf0955d 100644 --- a/hdl/testbench.v +++ b/hdl/testbench.v @@ -9,12 +9,15 @@ module testbench; //Outputs wire [7:0] led; - + wire rot_a_i; + wire rot_b_i; + //Instantiate the Unit Under Test (UUT) mips_system uut ( .clk(mips_clk), .rst(mips_rst), - + .rot_a_i(rot_a_i), + .rot_b_i(rot_b_i), .led(led) ); diff --git a/hdl/wb_rot_ctrl.v b/hdl/wb_rot_ctrl.v new file mode 100644 index 0000000..324f591 --- /dev/null +++ b/hdl/wb_rot_ctrl.v @@ -0,0 +1,69 @@ +`timescale 1ns / 1ps + +module wb_rot_ctrl #(parameter BASE_ADDR = 32'h00000400)( + input clk_i, + input rst_i, + + // wb signals + input [31:0] dat_i, + output [31:0] dat_o, + input [31:0] adr_i, + input we_i, + input [3:0] sel_i, + input cyc_i, + input stb_i, + output ack_o, + + input rot_a_i, + input rot_b_i, + output [7:0] led_o +); + +wire[7:0] data; +wire data_val; +wire[7:0] step; +wire step_val; + +wire[7:0] rot_data; +wire[7:0] rot_step; + +wb_slave_ctrl #(BASE_ADDR) wb_slave_ctrl ( + .wb_clk_i(clk_i), + .wb_rst_i(rst_i), + .wb_dat_i(dat_i), + .wb_adr_i(adr_i), + .wb_we_i(we_i), + .wb_sel_i(sel_i), + .wb_cyc_i(cyc_i), + .wb_stb_i(stb_i), + + .wb_dat_o(dat_o), + .wb_ack_o(ack_o), + + .data_o(data), + .data_val_o(data_val), + .step_o(step), + .step_val_o(step_val), + + .data_i(rot_data), + .step_i(rot_step) +); + +rot_ctrl rot_ctrl( + .clk_i(clk_i), + .rst_i(rst_i), + .rot_a_i(rot_a_i), + .rot_b_i(rot_b_i), + + .data_i(data), + .data_val_i(data_val), + .step_i(step), + .step_val_i(step_val), + + .data_o(rot_data), + .step_o(rot_step), + + .led_o(led_o) +); + +endmodule diff --git a/hdl/wb_rot_ctrl_testbench.v b/hdl/wb_rot_ctrl_testbench.v new file mode 100644 index 0000000..ec43a4b --- /dev/null +++ b/hdl/wb_rot_ctrl_testbench.v @@ -0,0 +1,82 @@ +`timescale 1ns / 1ps + +module wb_rot_ctrl_testbench; + + // Inputs + reg clk_i; + reg rst_i; + reg [31:0] dat_i; + reg [31:0] adr_i; + reg we_i; + reg [3:0] sel_i; + reg cyc_i; + reg stb_i; + reg rot_a_i; + reg rot_b_i; + + // Outputs + wire [31:0] dat_o; + wire ack_o; + wire [7:0] led; + + // Instantiate the Unit Under Test (UUT) + wb_rot_ctrl uut ( + .clk_i(clk_i), + .rst_i(rst_i), + .dat_i(dat_i), + .dat_o(dat_o), + .adr_i(adr_i), + .we_i(we_i), + .sel_i(sel_i), + .cyc_i(cyc_i), + .stb_i(stb_i), + .ack_o(ack_o), + .rot_a_i(rot_a_i), + .rot_b_i(rot_b_i), + .led(led) + ); + + initial begin + forever begin + clk_i = ~clk_i; + #100; + end + end + + initial begin + // Initialize Inputs + clk_i = 0; + rst_i = 0; + dat_i = 0; + adr_i = 0; + we_i = 0; + sel_i = 0; + cyc_i = 0; + stb_i = 0; + rot_a_i = 0; + rot_b_i = 0; + + // Wait 100 ns for global reset to finish + #100; + + rst_i = 1; + #100; + rst_i = 0; + + #100; + cyc_i = 1; + stb_i = 1; + we_i = 1; + adr_i = 1; + dat_i = 8'b00001111; + + #100; + #100; + #100; + + cyc_i = 0; + stb_i = 0; + end + +endmodule + diff --git a/hdl/wb_slave_ctrl.v b/hdl/wb_slave_ctrl.v new file mode 100644 index 0000000..95e5d18 --- /dev/null +++ b/hdl/wb_slave_ctrl.v @@ -0,0 +1,76 @@ +`timescale 1ns / 1ps + +module wb_slave_ctrl #(parameter BASE_ADDR = 32'h00000400)( + input wb_clk_i, + input wb_rst_i, + input [31:0] wb_dat_i, + input [31:0] wb_adr_i, + input wb_we_i, + input [3:0] wb_sel_i, + input wb_cyc_i, + input wb_stb_i, + + output reg [31:0] wb_dat_o, + output wb_ack_o, + + output reg[7:0] data_o, + output reg[7:0] step_o, + output reg data_val_o, + output reg step_val_o, + + input [7:0] data_i, + input [7:0] step_i +); + + localparam REG_DATA = BASE_ADDR + 0; + localparam REG_STEP = BASE_ADDR + 1; + + reg dat_ready = 0; + + assign read_i = wb_cyc_i & wb_stb_i & !wb_we_i; + assign write_i = wb_cyc_i & wb_stb_i & wb_we_i; + + assign wb_ack_o = (wb_cyc_i && wb_stb_i) && (data_val_o || step_val_o || dat_ready); + + always @(posedge wb_clk_i) + if( write_i && wb_adr_i == REG_DATA ) + begin + data_o <= wb_dat_i; + data_val_o <= 1; + end + else + begin + data_o <= 0; + data_val_o <= 0; + end + + always @(posedge wb_clk_i) + if( write_i && wb_adr_i == REG_STEP ) + begin + step_o <= wb_dat_i; + step_val_o <= 1; + end + else + begin + step_o <= 0; + step_val_o <= 0; + end + + always @(posedge wb_clk_i) + if( read_i && wb_adr_i == REG_DATA ) + begin + wb_dat_o <= data_i; + dat_ready <= 1; + end + else if( read_i && wb_adr_i == REG_STEP ) + begin + wb_dat_o <= step_i; + dat_ready <= 1; + end + else + begin + wb_dat_o <= 0; + dat_ready <= 0; + end + +endmodule diff --git a/hdl/wb_slave_ctrl_testbench.v b/hdl/wb_slave_ctrl_testbench.v new file mode 100644 index 0000000..36640fd --- /dev/null +++ b/hdl/wb_slave_ctrl_testbench.v @@ -0,0 +1,90 @@ +`timescale 1ns / 1ps + +module wb_slave_ctrl_testbench; + + // Inputs + reg wb_clk_i; + reg wb_rst_i; + reg [31:0] wb_dat_i; + reg [4:0] wb_adr_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg wb_cyc_i; + reg wb_stb_i; + reg [7:0] data_i; + reg [7:0] step_i; + + // Outputs + wire [31:0] wb_dat_o; + wire wb_ack_o; + wire [7:0] data_o; + wire [7:0] step_o; + wire data_val_o; + wire step_val_o; + + // Instantiate the Unit Under Test (UUT) + wb_slave_ctrl uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_we_i(wb_we_i), + .wb_sel_i(wb_sel_i), + .wb_cyc_i(wb_cyc_i), + .wb_stb_i(wb_stb_i), + .wb_dat_o(wb_dat_o), + .wb_ack_o(wb_ack_o), + .data_o(data_o), + .step_o(step_o), + .data_val_o(data_val_o), + .step_val_o(step_val_o), + .data_i(data_i), + .step_i(step_i) + ); + + initial begin + forever begin + wb_clk_i = ~wb_clk_i; + #100; + end + end + + + initial begin + // Initialize Inputs + wb_clk_i = 0; + wb_rst_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + wb_we_i = 0; + wb_sel_i = 0; + wb_cyc_i = 0; + wb_stb_i = 0; + data_i = 0; + step_i = 0; + + // Wait 100 ns for global reset to finish + #100; + + wb_rst_i = 1; + #100; + wb_rst_i = 0; + + #100; + data_i = 8'b00001111; + step_i = 8'b00001010; + wb_cyc_i = 1; + wb_stb_i = 1; + wb_we_i = 0; + wb_adr_i = 1; + + #100; + #100; + #100; + + wb_cyc_i = 0; + wb_stb_i = 0; + end + +endmodule + diff --git a/sw/test.asm b/sw/test.asm index eac3c7e..a77f76e 100644 --- a/sw/test.asm +++ b/sw/test.asm @@ -1,20 +1,12 @@ .global entry .data /* data section*/ - .word 0x0001 - .word 0x0002 - .word 0xFFFF + .word 0x00AF + .word 0x0400 .text /* code goes to text section*/ .ent entry entry: - lw $t0, 0x200 /* t0 = 1*/ - lw $t1, 0x201 /* t1 = 1*/ - add $t0, $t0, $t1 /* t0 = t0 + t1 = 2*/ - add $t0, $t0, 0xB /* t0 = t0 + 0xB == 0xD*/ - sub $t0, $t0, $t1 /* t0 = t0 - $t1 == 0xC*/ - or $t0, $t0, 0x10 /* t0 = t0 | 0x10 == 0x1C*/ - xor $t0, $t0, $t1 /* t0 = t0 ^ t1 == 0x1D*/ - slt $t0, $t0, $t1 /* t0 = t0 < t1 == 0*/ - add $t0, $t0, $t1 /* t0 = t0 + t1 == 1*/ - beq $t0, $t1, entry /* PC = entry if t0 == t1*/ + lw $t2, 0x200 + lw $t0, 0x201 + sw $t2, ($t0) .end entry |