// HHP 17 December 2019 // // This is the second level module. It is instantiated in "baseline_c5gx.v". // // The purpose of this module is to instantiate the MicroBlitz code and tie the // input and output of the core to the individual pins of the FGPA. // module SecondLevelMain ( input logic clk_slow, // 50 MHz input logic clk_fast, // 125 MHz input logic [9:0] SW, // 10 switches, with up=1, down=0 input logic [3:0] KEY, // 4 buttons, with up=1, down=0 output logic [7:0] LEDG, // 8 green LEDs, with 1=on output logic [9:0] LEDR, // 10 red LEDs, with 1=on output logic [6:0] HEX0, // rightmost 7-segment digit output logic [6:0] HEX1, // . (See SEVEN_SEG_DECODER module) output logic [6:0] HEX2, // . output logic [6:0] HEX3, // . leftmost 7-segment digit // inout logic [35:0] GPIO, // 36 digital pins input logic UART_RX, // Serial (through USB #2) output logic UART_TX // . ); wire [3:0] BUTTON; // Buttons, with down=1 assign BUTTON [3:0] = ~KEY [3:0]; // assign GPIO[35] = SW[3]; // assign LEDR[9] = GPIO[33]; // assign LEDG[0] = SW[0]; // assign LEDG[1] = ~SW[0]; // assign LEDG[3] = clk; // assign LEDG[4] = ~clk; // assign HEX3[6:0] = SW[6:0]; // Test all segments of HEX display wire [63:0] value64; wire [63:0] csr_prevpc; wire [15:0] csr_cause; wire [35:0] pc_curr; wire [3:0] nibble0, nibble1, nibble2, nibble3; wire [3:0] state_out; // wire selectable_clk; // wire clock_to_core; // assign selectable_clk = SW[2] ? clk_fast : clk_slow; // assign clock_to_core = SW[0] ? BUTTON[1] : selectable_clk; /************************* MicroBlitz *************************/ CONTROL MyControl ( // .clock (clock_to_core), // system clock or BUTTON for single-stepping .clock (clk_slow), .reset_in (BUTTON[0]), .digital_input ({56'b0, SW[9:2]}), .digital_output (value64), .clk50MHz (clk_slow), .clk125MHz (clk_fast), .UART_RX (UART_RX), .UART_TX (UART_TX), .csr_prevpc_out (csr_prevpc), .csr_cause_out (csr_cause), .pc_of_current_inst (pc_curr), .state_out (state_out) ); // ********** NOTE: THE FOLLOWING ENUM SHOULD MACTH THE SAME ENUM IN "MicroBlitz.sv"! ********** // Finite-State-Machine states (4 bits) typedef enum logic [3:0] { BEGIN_STATE, PRE_EXEC_STATE, EXEC_STATE, RD_WR_STATE, BRANCH_STATE, EXCEPT_STATE, FENCE_STATE, SLEEP_STATE, ILLEGAL_STATE } STATE_TYPE; always_comb begin case (state_out) BEGIN_STATE: LEDG [7:0] = 8'b0000_0000; PRE_EXEC_STATE: LEDG [7:0] = 8'b0000_1000; EXEC_STATE: LEDG [7:0] = 8'b0000_0001; // Normal running states appear OR'ed as 0000_0111 RD_WR_STATE: LEDG [7:0] = 8'b0000_0010; // . BRANCH_STATE: LEDG [7:0] = 8'b0000_0100; // . EXCEPT_STATE: LEDG [7:0] = 8'b0011_0000; // Exception looping will light up ..11_.... FENCE_STATE: LEDG [7:0] = 8'b0111_0000; // FENCE will light up as 0111_0000 SLEEP_STATE: LEDG [7:0] = 8'b1100_0011; // Sleep state will light up 1100_0011 default: LEDG [7:0] = 8'b1111_1111; // ILLEGAL_STATE endcase end always_comb begin // If button 1 is pressed, display csr_cause... if (BUTTON[1]) begin nibble3 = csr_cause [15 :12]; nibble2 = csr_cause [11 :8 ]; nibble1 = csr_cause [7 :4 ]; nibble0 = csr_cause [3 :0 ]; end // If button 2 is pressed, display LSB 16 bits of csr_prevpc... else if (BUTTON[2]) begin nibble3 = csr_prevpc [15 :12]; nibble2 = csr_prevpc [11 :8 ]; nibble1 = csr_prevpc [7 :4 ]; nibble0 = csr_prevpc [3 :0 ]; end // If button 3 is pressed, display pc... else if (BUTTON[3]) begin nibble3 = pc_curr [35 :32]; // NOTE, MSB nibble is 0=Kernel, 4=Boot, 8=Virtual nibble2 = pc_curr [11 :8 ]; nibble1 = pc_curr [7 :4 ]; nibble0 = pc_curr [3 :0 ]; end // Otherwise, display LSB 16 bits of DIGITAL OUT value... else begin nibble3 = value64 [15 :12]; nibble2 = value64 [11 :8 ]; nibble1 = value64 [ 7 :4 ]; nibble0 = value64 [ 3 :0 ]; end end SEVEN_SEG_DECODER my_7_seg_decoder_0 (nibble0, HEX0); SEVEN_SEG_DECODER my_7_seg_decoder_1 (nibble1, HEX1); SEVEN_SEG_DECODER my_7_seg_decoder_2 (nibble2, HEX2); SEVEN_SEG_DECODER my_7_seg_decoder_3 (nibble3, HEX3); assign LEDR[9:2] = value64[7:0]; assign LEDR[1:0] = 0; /**********************************************************************/ /********************** UART SERIAL TESTING ********************** // Using the 50 MHz clock // For 300 baud... // 50,000,000 / 1200 = 41,666.66 Clocks Per Bit. // For 9600 baud... // 50,000,000 / 9600 = 5208.33 Clocks Per Bit. // For 19200 baud... // 50,000,000 / 19200 = 2604.17 Clocks Per Bit. // For 115,200 baud... // 50,000,000 / 115,200 = 434 Clocks Per Bit. // For 230,400 baud... // 50,000,000 / 230,400 = 217.01 Clocks Per Bit. // // Using the 125 MHz clock // For 230,400 baud... // 125,000,000 / 230,400 = 542.53 Clocks Per Bit. wire [7:0] data8; wire [7:0] data_plus_one; wire data8_avail; uart_rx #(.CLKS_PER_BIT(543)) My_uart_rx (.clock (clk_fast), .i_rx (UART_RX), .o_data_avail (data8_avail), .o_data_byte (data8) ); uart_tx #(.CLKS_PER_BIT(543)) My_uart_tx (.clock (clk_fast), .i_data_avail (data8_avail), .i_data_byte (data_plus_one), .o_active (), .o_tx (UART_TX), .o_done () ); assign data_plus_one = data8 + 8'b0000_0001; // Type 'a' and 'b' will be echoed ********************************************************************************/ /********************** UART SERIAL TESTING - tested, works ********************** // Using the 50 MHz clock // For 300 baud... // 50,000,000 / 1200 = 41,666.66 Clocks Per Bit. // For 9600 baud... // 50,000,000 / 9600 = 5208.33 Clocks Per Bit. // For 19200 baud... // 50,000,000 / 19200 = 2604.17 Clocks Per Bit. // For 115,200 baud... // 50,000,000 / 115,200 = 434 Clocks Per Bit. // For 230,400 baud... // 50,000,000 / 230,400 = 217.01 Clocks Per Bit. // // Using the 125 MHz clock // For 230,400 baud... // 125,000,000 / 230,400 = 542.53 Clocks Per Bit. // parameter c_CLKS_PER_BIT = 41667; // 300 baud // parameter c_CLKS_PER_BIT = 2604; // 19,200 baud // parameter c_CLKS_PER_BIT = 434; // 115,200 baud parameter c_CLKS_PER_BIT = 543; // 230,400 baud // THE FOLLOWING CODE WILL ECHO INPUT TO OUTPUT. wire [7:0] recv_data8; wire recv_data8_ready; reg [7:0] transmit_byte_reg; reg transmit_ready_reg; wire o_Tx_Active; wire o_Tx_Done; uart_rx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) My_uart_rx (.clock (clk_fast), .i_rx (UART_RX), .o_data_avail (recv_data8_ready), // Will go high for 1 clock cycle when byte recv'd. .o_data_byte (recv_data8) ); uart_tx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) My_uart_tx (.clock (clk_fast), .i_data_avail (transmit_ready_reg), .i_data_byte (transmit_byte_reg), .o_active (o_Tx_Active), // Don't care, but display it on LEDG[1] .o_tx (UART_TX), // previously was connected to GPIO[35] .o_done (o_Tx_Done) // Don't care, but display it on LEDG[0] ); assign LEDR[9:2] = transmit_byte_reg; assign LEDR[1] = ~UART_RX; assign LEDR[0] = transmit_ready_reg; assign LEDG[7] = 0; assign LEDG[6] = ~UART_TX; assign LEDG[5] = o_Tx_Active; assign LEDG[4] = o_Tx_Done; assign LEDG[3:0] = BUTTON[3:0]; SEVEN_SEG_DECODER my_7_seg_decoder_0 (LEDR[5:2], HEX0); // Show transmited byte in hex SEVEN_SEG_DECODER my_7_seg_decoder_1 (LEDR[9:6], HEX1); SEVEN_SEG_DECODER my_7_seg_decoder_2 (SW[5:2], HEX2); // Show switches in hex SEVEN_SEG_DECODER my_7_seg_decoder_3 (SW[9:6], HEX3); reg prev_button_pressed; always_ff @(posedge clk_fast) begin if (BUTTON[0] & ~prev_button_pressed) // If button pressed, transmit the data on switches. begin transmit_byte_reg <= SW[9:2]; transmit_ready_reg <= 1; prev_button_pressed <= 1; end else if (~BUTTON[0] & prev_button_pressed) // If button just released. begin prev_button_pressed <= 0; end else if (recv_data8_ready) // Otherwise, if data received, then transmit same byte. begin transmit_byte_reg <= recv_data8; transmit_ready_reg <= 1; end else // Otherwise, transmit nothing. begin transmit_ready_reg <= 0; end end ********************************************************************************/ /*************** Code to increment a counter and display all bits *************** // Press each of the 4 buttons to reveal the entire 64 bit hex value (4 * 4 hex digits). reg [63:0] counter64 = 0; always_ff @ (posedge clk_fast) counter64 <= counter64 + 1; always_comb begin if (BUTTON[0]) begin nibble0 = counter64 [3 :0 ]; nibble1 = counter64 [7 :4 ]; nibble2 = counter64 [11:8 ]; nibble3 = counter64 [15:12]; end else if (BUTTON[1]) begin nibble0 = counter64 [19:16]; nibble1 = counter64 [23:20]; nibble2 = counter64 [27:24]; nibble3 = counter64 [31:28]; end else if (BUTTON[2]) begin nibble0 = counter64 [35:32]; nibble1 = counter64 [39:36]; nibble2 = counter64 [43:40]; nibble3 = counter64 [47:44]; end else if (BUTTON[3]) begin nibble0 = counter64 [51:48]; nibble1 = counter64 [55:52]; nibble2 = counter64 [59:56]; nibble3 = counter64 [63:60]; end else begin nibble0 = 4'b0; nibble1 = 4'b0; nibble2 = 4'b0; nibble3 = 4'b0; end end SEVEN_SEG_DECODER my_7_seg_decoder_0 (nibble0, HEX0); SEVEN_SEG_DECODER my_7_seg_decoder_1 (nibble1, HEX1); SEVEN_SEG_DECODER my_7_seg_decoder_2 (nibble2, HEX2); SEVEN_SEG_DECODER my_7_seg_decoder_3 (nibble3, HEX3); ********************************************************************************/ /*************** Code to increment a counter and display all bits *************** // Press each of the 4 buttons to reveal the entire 64 bit hex value (4 * 4 hex digits). reg [63:0] counter64 = 0; always_ff @ (posedge clk_fast) counter64 <= counter64 + 1; always_comb begin if (BUTTON[0]) begin nibble0 = counter64 [3 :0 ]; nibble1 = counter64 [7 :4 ]; nibble2 = counter64 [11:8 ]; nibble3 = counter64 [15:12]; end else if (BUTTON[1]) begin nibble0 = counter64 [19:16]; nibble1 = counter64 [23:20]; nibble2 = counter64 [27:24]; nibble3 = counter64 [31:28]; end else if (BUTTON[2]) begin nibble0 = counter64 [35:32]; nibble1 = counter64 [39:36]; nibble2 = counter64 [43:40]; nibble3 = counter64 [47:44]; end else if (BUTTON[3]) begin nibble0 = counter64 [51:48]; nibble1 = counter64 [55:52]; nibble2 = counter64 [59:56]; nibble3 = counter64 [63:60]; end else begin nibble0 = 4'b0; nibble1 = 4'b0; nibble2 = 4'b0; nibble3 = 4'b0; end end SEVEN_SEG_DECODER my_7_seg_decoder_0 (nibble0, HEX0); SEVEN_SEG_DECODER my_7_seg_decoder_1 (nibble1, HEX1); SEVEN_SEG_DECODER my_7_seg_decoder_2 (nibble2, HEX2); SEVEN_SEG_DECODER my_7_seg_decoder_3 (nibble3, HEX3); ********************************************************************************/ endmodule // Decoder for 7 segment display for Cyclone 5 GX // // 0 // ----- // | | // 5 | | 1 0 = ON // | 6 | 1 = OFF // ----- // | | // 4 | | 2 // | 3 | // ----- // module SEVEN_SEG_DECODER ( input logic [3:0] a, output logic [6:0] y ); always_comb case (a) // 654_3210 These are on: 4'h0: y = 7'b100_0000; // 0,1,2,3,4,5 4'h1: y = 7'b111_1001; // 1,2 4'h2: y = 7'b010_0100; // 0,1,3,4,6 4'h3: y = 7'b011_0000; // 0,1,2,3,6 4'h4: y = 7'b001_1001; // 1,2,5,6 4'h5: y = 7'b001_0010; // 0,2,3,5,6 4'h6: y = 7'b000_0010; // 0,2,3,4,5,6 4'h7: y = 7'b111_1000; // 0,1,2 4'h8: y = 7'b000_0000; // all 4'h9: y = 7'b001_1000; // 0,1,2,5,6 4'hA: y = 7'b000_1000; // 0,1,2,4,5,6 4'hB: y = 7'b000_0011; // 2,3,4,5,6 4'hC: y = 7'b100_0110; // 0,3,4,5 4'hD: y = 7'b010_0001; // 1,2,3,4,6 4'hE: y = 7'b000_0110; // 0,3,4,5,6 4'hF: y = 7'b000_1110; // 0,4,5,6 default: y = 7'b111_1111; endcase endmodule