hacdc-wiki/FPGAWorkshop16Notes.md
2024-06-12 21:48:44 -04:00

9.4 KiB
Executable File

this is known broke - will

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    11:23:27 01/28/2010
// Design Name:
// Module Name:    frequency_counter
// Project Name:
// Target Devices:
// Tool versions:
// Description: Verilog implementatino of the frequency counter reference
// design from Xilinx for Spartan 3E Starter Kit
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module frequency_counter(
    output [7:0] led,
    input [4:0] sw,
    output strataflash_oe,
    output strataflash_ce,
    output strataflash_we,
    inout [7:4] lcd_d,
    output lcd_rs,
    output lcd_rw,
    output lcd_e,
    input sma_clk,
    input clk_50mhz
    );

    // signals for counting the test clock
    reg [3:0] ab_switch_delay;
    reg a_count_ce, b_count_ce;
    reg [31:0] a_count, b_count;
    reg a_count_rst, b_count_rst;
    reg freq_for_measurement;
    wire test_clk;

    // signals for 1 second interrupt generation and couter switching
    reg ab_switch;
    reg [99:0] interrupt_delay;
    reg [25:0] one_second_count;
    reg one_second_pulse;
    reg interrupt;
    reg [7:0] source_control;

    // signals for processor interconnect
    reg [7:0] in_port;
    wire [7:0] out_port;
    wire write_strobe, read_strobe;
    wire [7:0] port_id;
    wire interrupt_ack;
    wire [17:0] instruction;
    wire [9:0] address;

    // lcd wires
    reg [7:0] lcd_reg;
    wire lcd_drive;
    wire lcd_output_data;

    // led reg
    reg [7:0] led_reg;

    // ring osscillator instantiations
    ring_osc logic_oscillator (.reset(source_control[6]),.osc_out(ring_oscillator));
    ring_osc2 logic_oscillator2 (.reset(source_control[6]),.osc_out(ring_oscillator2));

    // frequency selection mux - purely combinational
    always@(sma_clk or clk_50mhz or ring_oscillator or ring_oscillator2)
        if(source_control[1:0] == 2'b00)
            freq_for_measurement = sma_clk;
        else if(source_control[1:0] == 2'b01)
            freq_for_measurement = clk_50mhz;
        else if(source_control[1:0] == 2'b10)
            freq_for_measurement = ring_oscillator2;
        else
            freq_for_measurement = ring_oscillator;

    // global clock buffer the test clock
    BUFG buffer_clkin(.O(test_clk), .I(freq_for_measurement));

    // counter switch control
    always@(posedge test_clk)
    begin
        ab_switch_delay <= {ab_switch_delay[2:0], ab_switch};
        case(ab_switch_delay[3:1])
            3'b000: begin
                a_count_ce <= 1;
                b_count_ce <= 0;
                end
            3'b111: begin
                a_count_ce <= 0;
                b_count_ce <= 1;
            end
            default: begin
                a_count_ce <= 1;
                b_count_ce <= 0;
            end
        endcase
    end

    // test counters
    always@(posedge test_clk or posedge a_count_rst)
        if(a_count_rst)
            a_count <= 'b0;
        else if(a_count_ce)
            a_count <= a_count+1;
        else
            a_count <= a_count;

    always@(posedge test_clk or posedge b_count_rst)
        if(b_count_rst)
            b_count <= 'b0;
        else if(b_count_ce)
            b_count <= b_count+1;
        else
            b_count <= b_count;

    // one second interrupt generation and clock switching
/*  always@(posedge clk_50mhz)
    begin
        // divide by 50,000,000 to generate pulse
        if(one_second_count == 26'd49999999)
        begin
            one_second_count <= 'b0;
            one_second_pulse <= 1'b1;
        end
        else
        begin
            one_second_count <= one_second_count + 1;
            one_second_pulse <= 1'b0;
        end

        // delay 100 clock cycles before generating interrupt
        interrupt_delay <= {interrupt_delay[98:0], one_second_pulse};

        // interrupt generation
        if (interrupt_ack == 1'b1)
            interrupt <= 1'b0;
        else if (interrupt_delay[99] == 1'b1)
            interrupt <= 1'b1;
        else
            interrupt <= interrupt;

        // counter selection switch toggle's each second
        if (one_second_pulse == 1'b1)
            ab_switch <= ~ab_switch;
    end*/
always@(posedge clk_50mhz)
    begin
        // divide by 50,000,000 to generate pulse
        if(one_second_count == 26'd49999999)
        begin
            one_second_count <= 'b0;
            one_second_pulse <= 1'b1;
        end
        else
        begin
            one_second_count <= one_second_count + 1;
            one_second_pulse <= 1'b0;
        end
    end
always@(posedge clk_50mhz)

begin
            // delay 100 clock cycles before generating interrupt
        interrupt_delay <= {interrupt_delay[98:0], one_second_pulse};
end

always@(posedge clk_50mhz)
    begin
            // interrupt generation
        if (interrupt_ack == 1'b1)
            interrupt <= 1'b0;
        else if (interrupt_delay[99] == 1'b1)
            interrupt <= 1'b1;
        else
            interrupt <= interrupt;
end

always@(posedge clk_50mhz)
begin
    // counter selection switch toggle's each second
        if (one_second_pulse == 1'b1)
            ab_switch <= ~ab_switch;
        else
            ab_switch <= ab_switch;
        end


    // picoblaze instantiation
    kcpsm3 processor (.address(address),
        .instruction(instruction),
        .port_id(port_id),
        .write_strobe(write_strobe),
        .out_port(out_port),
        .read_strobe(read_strobe),
        .in_port(in_port),
        .interrupt(interrupt),
        .interrupt_ack(interrupt_ack),
        .reset(reset),
        .clk(clk_50mhz));
    fc_ctrl program_rom (.address(address),
        .instruction(instruction),
        .proc_reset(proc_reset),
        .clk(clk_50mhz));

    // processor input ports
    always@ (posedge clk_50mhz)
        case(port_id[7:4])
            // read A counter
            4'b0000: in_port <= a_count[7:0];
            4'b0001: in_port <= a_count[15:8];
            4'b0010: in_port <= a_count[23:16];
            4'b0011: in_port <= a_count[31:24];
            // read B counter
            4'b0100: in_port <= b_count[7:0];
            4'b0101: in_port <= b_count[15:8];
            4'b0110: in_port <= b_count[23:16];
            4'b0111: in_port <= b_count[31:24];
            // read slide switches
            4'b1000: in_port <= {3'b000, ab_switch, sw};
            // read LC Ddata at address 90 hex
            4'b1001: in_port <= {lcd_d, 4'b0000};
            // original design used a dont care condition
            // I've decided to let it retain its value.
            default: in_port <= in_port;
        endcase

    // output ports
    always@ (posedge clk_50mhz)
        if(write_strobe)
            case(port_id[3:0])
                // LED register at address 0x01
                4'b0001: led_reg <= out_port;
                // Counter reset controls at 0x02
                4'b0010: begin
                    a_count_rst <= out_port[0];
                    b_count_rst <= out_port[1];
                    end
                // LCD data/controls at 0x04
                4'b0100: begin
                    lcd_reg         <= out_port;
                    end
                // Source selection and control at 0x08
                4'b1000: source_control <= out_port;
            endcase

    // LCD controls
    assign lcd_rw_control = lcd_reg[1];
    assign lcd_drive = lcd_reg[3];
    assign lcd_output_data = lcd_reg [7:4];
    // LCD Outputs
    assign lcd_e = lcd_reg[0];
    assign lcd_rw = lcd_rw_control && lcd_drive;
    assign lcd_rs = lcd_reg[2];
    assign lcd_d = ((lcd_rw_control == 1'b0) && (lcd_drive == 1'b1)) ? lcd_output_data : 4'bZZZZ;

    // LED assignment
    //assign led = led_reg;
    // Debug assignments
    assign led[7]=led_reg[7]; //A counter
    assign led[6]=led_reg[0]; //B counter
    assign led[5]=a_count[10]; // should toggle at 8hz when enabled
    assign led[4]=b_count[10]; // should toggle at 8hz when enabled
    assign led[3]=one_second_count[24]; // should toggle very fast.
    assign led[2]=one_second_pulse; // once per second
    assign led[1]=interrupt_ack; //interrupt ack
    assign led[0]=interrupt; //interrupt

    // strataflash chip enable signals to disable onboard strataflash
    assign strataflash_we = 1'b1;
    assign strataflash_ce = 1'b1;
    assign strataflash_oe = 1'b1;

endmodule

Category:FPGAWorkshop