X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=techlibs%2Fgreenpak4%2Fcells_sim_digital.v;h=43d35d08f33c4c3c66ee49e585c756139de0bdf4;hb=ff785cdb46d6b1ddc19d5acc21b4d1236b3adf3f;hp=ccf9840c7b0408886e1f4b58e0206dd728378b35;hpb=4504dd78e9bba5b768fbc3a91e006c5679366e15;p=yosys.git diff --git a/techlibs/greenpak4/cells_sim_digital.v b/techlibs/greenpak4/cells_sim_digital.v index ccf9840c7..43d35d08f 100644 --- a/techlibs/greenpak4/cells_sim_digital.v +++ b/techlibs/greenpak4/cells_sim_digital.v @@ -30,6 +30,367 @@ module GP_CLKBUF(input wire IN, output wire OUT); assign OUT = IN; endmodule +module GP_COUNT14(input CLK, input wire RST, output reg OUT); + + parameter RESET_MODE = "RISING"; + + parameter COUNT_TO = 14'h1; + parameter CLKIN_DIVIDE = 1; + + reg[13:0] count = COUNT_TO; + + initial begin + if(CLKIN_DIVIDE != 1) begin + $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented"); + $finish; + end + end + + //Combinatorially output underflow flag whenever we wrap low + always @(*) begin + OUT <= (count == 14'h0); + end + + //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm. + //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now. + generate + case(RESET_MODE) + + "RISING": begin + always @(posedge CLK, posedge RST) begin + if(RST) + count <= 0; + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end + end + end + + "FALLING": begin + always @(posedge CLK, negedge RST) begin + if(!RST) + count <= 0; + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end + end + end + + "BOTH": begin + initial begin + $display("Both-edge reset mode for GP_COUNT14 not implemented"); + $finish; + end + end + + "LEVEL": begin + always @(posedge CLK, posedge RST) begin + if(RST) + count <= 0; + + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end + end + end + + default: begin + initial begin + $display("Invalid RESET_MODE on GP_COUNT14"); + $finish; + end + end + + endcase + endgenerate + +endmodule + +module GP_COUNT14_ADV(input CLK, input RST, output reg OUT, + input UP, input KEEP, output reg[7:0] POUT); + + parameter RESET_MODE = "RISING"; + parameter RESET_VALUE = "ZERO"; + + parameter COUNT_TO = 14'h1; + parameter CLKIN_DIVIDE = 1; + + initial begin + if(CLKIN_DIVIDE != 1) begin + $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented"); + $finish; + end + end + + reg[13:0] count = COUNT_TO; + + //Combinatorially output underflow flag whenever we wrap low + always @(*) begin + if(UP) + OUT <= (count == 14'h3fff); + else + OUT <= (count == 14'h0); + POUT <= count[7:0]; + end + + //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm. + //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now. + generate + case(RESET_MODE) + + "RISING": begin + always @(posedge CLK, posedge RST) begin + + //Resets + if(RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + else if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 14'h3fff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + + end + end + + "FALLING": begin + always @(posedge CLK, negedge RST) begin + + //Resets + if(!RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + else if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 14'h3fff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + + end + end + + "BOTH": begin + initial begin + $display("Both-edge reset mode for GP_COUNT14_ADV not implemented"); + $finish; + end + end + + "LEVEL": begin + always @(posedge CLK, posedge RST) begin + + //Resets + if(RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + else begin + + if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 14'h3fff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + + end + + end + end + + default: begin + initial begin + $display("Invalid RESET_MODE on GP_COUNT14_ADV"); + $finish; + end + end + + endcase + endgenerate + +endmodule + +module GP_COUNT8_ADV(input CLK, input RST, output reg OUT, + input UP, input KEEP, output reg[7:0] POUT); + + parameter RESET_MODE = "RISING"; + parameter RESET_VALUE = "ZERO"; + + parameter COUNT_TO = 8'h1; + parameter CLKIN_DIVIDE = 1; + + reg[7:0] count = COUNT_TO; + + initial begin + if(CLKIN_DIVIDE != 1) begin + $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented"); + $finish; + end + end + + //Combinatorially output underflow flag whenever we wrap low + always @(*) begin + if(UP) + OUT <= (count == 8'hff); + else + OUT <= (count == 8'h0); + POUT <= count; + end + + //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm. + //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now. + generate + case(RESET_MODE) + + "RISING": begin + always @(posedge CLK, posedge RST) begin + + //Resets + if(RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + //Main counter + else if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 8'hff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + + end + end + + "FALLING": begin + always @(posedge CLK, negedge RST) begin + + //Resets + if(!RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + //Main counter + else if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 8'hff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + + end + end + + "BOTH": begin + initial begin + $display("Both-edge reset mode for GP_COUNT8_ADV not implemented"); + $finish; + end + end + + "LEVEL": begin + always @(posedge CLK, posedge RST) begin + + //Resets + if(RST) begin + if(RESET_VALUE == "ZERO") + count <= 0; + else + count <= COUNT_TO; + end + + else begin + + if(KEEP) begin + end + else if(UP) begin + count <= count + 1'd1; + if(count == 8'hff) + count <= COUNT_TO; + end + else begin + count <= count - 1'd1; + + if(count == 0) + count <= COUNT_TO; + end + end + + end + end + + default: begin + initial begin + $display("Invalid RESET_MODE on GP_COUNT8_ADV"); + $finish; + end + end + + endcase + endgenerate + +endmodule + module GP_COUNT8( input wire CLK, input wire RST, @@ -41,12 +402,19 @@ module GP_COUNT8( parameter COUNT_TO = 8'h1; parameter CLKIN_DIVIDE = 1; + initial begin + if(CLKIN_DIVIDE != 1) begin + $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented"); + $finish; + end + end + reg[7:0] count = COUNT_TO; //Combinatorially output underflow flag whenever we wrap low always @(*) begin OUT <= (count == 8'h0); - OUT <= count; + POUT <= count; end //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm. @@ -55,24 +423,26 @@ module GP_COUNT8( case(RESET_MODE) "RISING": begin - always @(posedge CLK or posedge RST) begin - count <= count - 1'd1; - if(count == 0) - count <= COUNT_TO; - + always @(posedge CLK, posedge RST) begin if(RST) count <= 0; + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end end end "FALLING": begin - always @(posedge CLK or negedge RST) begin - count <= count - 1'd1; - if(count == 0) - count <= COUNT_TO; - + always @(posedge CLK, negedge RST) begin if(!RST) count <= 0; + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end end end @@ -84,6 +454,16 @@ module GP_COUNT8( end "LEVEL": begin + always @(posedge CLK, posedge RST) begin + if(RST) + count <= 0; + + else begin + count <= count - 1'd1; + if(count == 0) + count <= COUNT_TO; + end + end end default: begin @@ -362,20 +742,24 @@ module GP_PGEN(input wire nRST, input wire CLK, output reg OUT); parameter PATTERN_DATA = 16'h0; parameter PATTERN_LEN = 5'd16; + localparam COUNT_MAX = PATTERN_LEN - 1'h1; + reg[3:0] count = 0; - always @(posedge CLK) begin + always @(posedge CLK, negedge nRST) begin + if(!nRST) - OUT <= PATTERN_DATA[0]; + count <= 0; else begin - count <= count + 1; - OUT <= PATTERN_DATA[count]; - - if( (count + 1) == PATTERN_LEN) - count <= 0; + count <= count - 1'h1; + if(count == 0) + count <= COUNT_MAX; end end + always @(*) + OUT = PATTERN_DATA[count]; + endmodule module GP_SHREG(input nRST, input CLK, input IN, output OUTA, output OUTB);